一文搞懂图片优化技术

上篇文章,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
                    }
                ]
            }
        })
 ]

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

相关推荐
GoppViper16 分钟前
uniapp中实现<text>文本内容点击可复制或拨打电话
前端·后端·前端框架·uni-app·前端开发
Sam902925 分钟前
【Webpack--007】处理其他资源--视频音频
前端·webpack·音视频
Code成立27 分钟前
HTML5精粹练习第1章博客
前端·html·博客·html5
架构师ZYL38 分钟前
node.js+Koa框架+MySQL实现注册登录
前端·javascript·数据库·mysql·node.js
一只小白菜~2 小时前
实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??
前端·javascript·websocket·sse·ajax轮询
计算机学姐2 小时前
基于python+django+vue的在线学习资源推送系统
开发语言·vue.js·python·学习·django·pip·web3.py
晓翔仔2 小时前
CORS漏洞及其防御措施:保护Web应用免受攻击
前端·网络安全·渗透测试·cors·漏洞修复·应用安全
GISer_Jing3 小时前
【前后端】大文件切片上传
前端·spring boot
csdn_aspnet3 小时前
npm 安装 与 切换 淘宝镜像
前端·npm·node.js
蜡笔小新星3 小时前
切换淘宝最新镜像源npm
vue.js·经验分享·学习·npm·node.js