一文搞懂图片优化技术

上篇文章,Brotli压缩算法在WEB中的应用最佳实践,介绍了js、css、html文件压缩优化技术,对于前端性能优化图片优化的重要性不下于js等文件的优化,本篇文章着重介绍图片压缩、图片下载等多种图片优化技术。

一、图片优化之图片压缩

什么是最佳的图片压缩,能实现如下3点就是最佳的图片压缩:

1、大幅度缩小图片大小

2、图片质量不降低

3、方便快捷

介于上述3点,经调研实践,得出基于tinify算法的图片压缩脚本开发为最佳实践,其优势在于:

1、图片可减小大小80%

2、tinify算法处理图片对质量的影响肉眼几乎无法分辨

3、脚本一键启用,复用方便,可以用于任何vue、react等项目

代码如下:

javascript 复制代码
//compress-image.js
const fs = require('fs')
const path = require('path')
const tinify = require('tinify')
// 这个key上官网申请,邮箱注册即可
tinify.key = 'Qv29t*****kwHxs' 
// 获取项目根目录
const projectRoot = process.cwd()
// 定义 assets 目录的路径
const assetsDir = path.join(projectRoot, 'src/assets')
// 获取项目中的所有图片文件
const imageFiles = getImageFiles(assetsDir)
// 压缩每个图片文件并保留原始文件名
imageFiles.forEach(file => {
  const filePath = path.resolve(assetsDir, file)
  const source = fs.readFileSync(filePath)
  try {
    tinify.fromBuffer(source).toFile(filePath, err => {
      if (err) {
        console.log(`Error compressing ${file}: ${err}`)
      } else {
        console.log(`${file} has been compressed`)
      }
    })
  } catch (err) {
    console.log(`Error compressing ${file}: ${err}`)
  }
})
function getImageFiles(directoryPath) {
  let images = []
  // 获取目录下的文件列表
  const files = fs.readdirSync(directoryPath)
  files.forEach(function(file) {
    const filePath = path.join(directoryPath, file)
    // 检查文件的类型
    if (fs.statSync(filePath).isFile()) {
      // 检查文件扩展名是否为图片格式(这里只列举了常见的图片格式,根据需要进行调整)
      const ext = path.extname(filePath).toLowerCase()
      if (ext === '.jpg' || ext === '.jpeg' || ext === '.png') {
        images.push(filePath)
      }
    } else {
      // 如果是目录,递归获取该目录下的所有图片文件
      const subDirectoryPath = path.join(directoryPath, file)
      const subDirectoryImages = getImagesFromDirectory(subDirectoryPath)
      images = images.concat(subDirectoryImages)
    }
  })
  return images
}
// 运行
node compress-image.js

压缩效果展示:

二、图片优化之响应式下载

提到响应式下载,不得不提到img标签 srcset 和 sizes这2个属性

srcset属性允许定义多个不同尺寸的图片,然后浏览器将自动选择最适合用户屏幕尺寸的图片,如:

ini 复制代码
<img srcset="
    image/pic_300.jpg 300w,
    image/pic_800.jpg 800w,
    image/pic_1300.jpg 1300w
"/>

此优势在于在小屏幕上,浏览器将下载一个较小的图像,而大屏幕仍将获得高分辨率的图像。这将显著减少传输给用户的数据量,并加快页面加载速度,繁琐的地方在于你的准备多个图片。srcset也可用在分辨率优化上。

sizes属性必须配合srcset属性一起使用才有效,单独使用无效。但是srcset可以单独使用。

ini 复制代码
<img
  srcset="
    image/pic_300.jpg 300w,
    image/pic_800.jpg 800w,
    image/pic_1300.jpg 1300w
  "
  sizes="(max-width: 500px) 50vw, (max-width: 800px) 100vw, 1200px"
/>

在定义了sizes属性后,浏览器会依次执行以下操作:

1、查看当前设备宽度;

2、依次检查sizes属性列表中第一个为真的媒体条件;

3、查看该媒体条件对应的槽的大小;

4、通过槽的大小,加载对应的srcset列表中与槽的大小最接近的图像。

三、图片优化之服务器优化

无论是亚马逊服务器还是阿里云服务器都有图片优化技巧。如CDN技术,这里要讲的是服务器根据请求动态处理返回图片尺寸技术,这种方式效果类似于响应式下载,不同在于图片是动态处理的。

阿里云服务可一键开启,亚马逊服务器需自己配置。他们的请求方式类似,都在在请求图片url后面添加图片尺寸参数。需要一定费用。

这种场景通常是用于一次请求数十上百个图片上,原图片尺寸比较大比如宽度为1000px,但我实际之需要100px,此时处理请求尺寸,拿到适合的图片,将大幅度减少图片下载压力。

四、图片优化之取消图片下载

接着上个服务优化技术,在项目业务中有这样的场景,选择电子书阅读,接口一次返回157个书目,页面需要渲染书封面,此时一次请求下载157张图片,大量的请求排队给服务器和浏览器带来压力。这样的场景中测试,电脑8g内存只需切换路由来回点击3次页面几乎卡死。

如何解决了,可以用分页,可以用图片懒加载,也可以用取消图片下载方式。

当路由切换时,页面销毁时,则取消所有在排队的下载任务,这种思路同样也适用于接口请求。

scss 复制代码
 onBeforeUnmount(() => {
      if (imgRef.value) {
        imgRef.value.src = '' // 设置src为空字符串,取消加载
      }
 })

取消请求接口与取消图片下载不一样,这里不再赘述。

五、图片优化之懒加载

懒加载优先显示可视区域的图片而不是一次加载全部的图片,当需要显示时,再发送请求加载图片。

懒加载的实现方式很多,可自定义实现,也可以用插件,如vue-lazyload,其实现原理、方式这里不再赘述,推荐用vue-lazyload简单好用。

六、图片优化之阿里巴巴iconfont图标

阿里巴巴矢量图iconfont是非常方便的图标使用方式,你是否因为每迭代一个版本,UI就换一个图标样式而烦恼,同一种含义用不同的图标,同样的图片尺寸、颜色又不一样,此时推荐使用阿里巴巴iconfont,他不仅是很好的图标使用方式,方便三端使用,更重要的是形成UI设计标准。

其使用流程如下:

1、UI设计师按要求设计图标并上传之账户

2、其他开发用户上账户下载使用。

这会增加UI工作量,所以说服你的UI设计师来使用是最麻烦的事情,但是你会发现,越用越好用。

端上使用的方式官网有讲解,这里提供一个最方便,最稳妥的方式:

下载svg图标到本地,使用symbol方式封装svg图标组件。

具体代码不展示了,如果是vite,可以用vite-plugin-svg-icons依赖插件:

javascript 复制代码
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import path from 'path'
export default () => {
  return {
    plugins: [
      createSvgIconsPlugin({
        // Specify the icon folder to be cached
        iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
        // Specify symbolId format
        symbolId: 'icon-[dir]-[name]',
      }),
    ],
  }
}

七、图片优化之雪碧图

雪碧图是将多个图标组合到一张图片上,减少图片请求次数。这里要说的,大多数项目开发都是赶时间,所以哪有时间去处理图片,调试雪碧图,这种方式常在业务做完后,回头审视项目优化来处理。

八、图片优化之构建优化

构建优化为图片优化最后一步,即在打包构建包阶段。此时不管你是用webpack还是vite都有相应的优化方式,其对图片的压缩可与第一种图片压缩方式叠加效果。

webpack image-webpack-loader

scss 复制代码
config.module
    .rule('images')
    .test(/.(png|jpe?g|gif)(?.*)?$/)
    // Add image-webpack-loader to optimize images
    .use('image-webpack-loader')
    .loader('image-webpack-loader')
    .options({ bypassOnDebug: true })
    .end();

vite vite-plugin-imagemin

php 复制代码
 plugins: [vue(),
        // 图片压缩
        viteImagemin({
            gifsicle: {
                optimizationLevel: 7,
                interlaced: false
            },
            optipng: {
                optimizationLevel: 7
            },
            mozjpeg: {
                quality: 20
            },
            pngquant: {
                quality: [0.8, 0.9],
                speed: 4
            },
            svgo: {
                plugins: [
                    {
                        name: 'removeViewBox'
                    },
                    {
                        name: 'removeEmptyAttrs',
                        active: false
                    }
                ]
            }
        })
 ]

本文总体介绍图片压缩、图片下载、图片渲染、图标管理、构建优化等多种图片优化手段,希望对你有所帮助。

相关推荐
崔庆才丨静觅2 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了3 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅3 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment4 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅4 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊4 小时前
jwt介绍
前端
爱敲代码的小鱼4 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax