再战前端性能优化之图片优化,图片资源减少了57% - zptime/blog GitHub Wiki
图片的优化处理汇总,包括选择合适的图片格式,图片压缩,CSS Sprites(雪碧图,CSS 精灵),图片懒加载,CSS 替换实现,base64 格式,iconfont 字体图标,使用 CDN等等
前言
之前写了一篇前端性能优化实战 从 30s 到 2s的文章,是从大方向上进行优化的,主要是插件的按需引入
,加上 gzip 压缩
配置。
本篇还是优化同一个系统,不过是从细节优化入手的,主要介绍图片的优化处理
。
图片优化方案
- 图片格式:常用的图片格式有 JPG、PNG、SVG、WebP 等等,选择适合的
- 图片压缩:对于清晰度要求不高的图片,可以进行压缩处理
- 手动压缩推荐 tinypng
- webpack 插件
image-webpack-loader
压缩
- CSS Sprites(雪碧图,CSS 精灵):将多个小图标合成一张图,减少 HTTP 请求次数。通过定位(
backround-position
)来显示对应的图片,这个对于细节要求比较高- 让 UI 帮我们合成,当然自己能合成的话更好
webpack-spritesmith
插件
- 图片懒加载
- 对于那种图片比较多的页面,仅展示可视窗口内的图片,其他的等滚动到可视窗口再加载;
- 图片轮播组件也可以使用懒加载
- 懒加载方案:图片地址存放 img 标签的某个属性上,例如
data-src
,当图片再可视窗口范围内时,将src
属性替换成图片地址data-src
的值。 - Intersection Observer API - Web API 接口 | MDN
- vue-lazyload
- CSS 替换实现
- 尽量用 CSS 实现图片,不能再考虑切图
- 使用 CSS3 属性时,尽量考虑到
GPU 硬件加速
- 响应式图片加载:不同分辨率的设备使用不同尺寸的图片,适合手机端
- base64 格式
- 将图片 src 换成 base64 格式加载,减少网络请求
- 图片经过 base64 编码后会变大,增大 HTML 页面的大小,影响加载速度
- 所以要合理使用此方式,常用在 webpack 的
url-loader
中使用
- iconfont 字体图标:减少 HTTP 请求次数
- 使用 CDN:有些大图片可以直接放在服务器上,降低访问延时
实战
优化前
图片资源为4.6MB,图片个数为110个:
imagemin-webpack-plugin 图片压缩
根据“优化前分析” => “构建后文件分析”,有四张图片太大,需要优化处理
因为系统需要支持大屏幕显示,一般用的图片都是三倍图,所以图片都会比较大,需要合理处理一下。
(1)配置代码
easywebpack 内置了一些插件,只需要进行简单的配置就可以开启关闭,当然也可以覆盖默认配置,进行自定义配置
// 安装
$ npm install imagemin-webpack-plugin --save-dev
// 配置webpack.config.js
module.exports = {
plugins: [
{ // 1. 禁用内置图片压缩插件配置(imagemin-webpack-plugin),默认启用
// imagemini: false,
// 2. 当然也可以自定义配置
imagemini: {
enable: true,
env: ["prod"],
type: "client",
name: "imagemin-webpack-plugin",
entry: "default",
args: {
test: /\.(jpe?g|png|gif|svg)$/i,
optipng: {
optimizationLevel: 9,
},
pngquant: {
// 压缩质量
quality: "20-30",
},
},
},
},
],
};
(2)配置对比
图片资源从 4.6MB 变为 1.7MB
,当然我配置的20-30
肯定是有些极端的,正常情况下配置70-90
。
我配置的这么低了,还有一张图片还是很大,可以考虑对其进行单独处理,先手动压缩一下,在进行其他处理
url-loader base64 转化
小图片考虑使用 url-loader
直接转成 base64
格式,减少网络请求
(1)配置代码:
easywebpack 集成了 url-loader 插件,默认使用如下:
// 配置webpack.config.js
module.exports = {
module: {
rules: [
{
// 1. 默认禁用
// urlimage: false
// 2. 自定义处理
urlimage: {
options: { limit: 1024 * 5 }, // 小于5KB转为base64,大于的不转
},
},
],
},
};
(2)配置对比
配置后,图片资源从 4.6MB 变为 4.4MB
,图片小于 5KB
的都转为 base64 了,图片个数变为50个,减少了60个
同时开启
有一些图片压缩前很大,imagemin
之后很小,这些文件如果用 imagemin-webpack-plugin
处理之后,就不会再转为 base64 格式了,因为 loader
在 plugin
之前执行,url-loader
limit 比较的是压缩前的大小。
如果同时开启图片压缩和 base64 转化,结果是仅压缩了,没有转为 base64
解决方案:使用 image-webpack-loader 替代 imagemin-webpack-plugin
(1)配置代码:
需要用如下的配置覆盖默认的配置:
// 安装插件
$ npm install image-webpack-loader --save-dev
// 配置webpack.config.js
module.exports = {
plugins: [
{
imagemini: false, // 禁用
},
],
module: {
rules: [
{
// urlimage: false // 默认禁用
urlimage: {
use: [
{
loader: "url-loader",
options: {
limit: 1024 * 5, // 小于5KB转为base64
fallback: "file-loader",
name: `img/[name].[hash:8].[ext]`,
},
},
{
loader: "image-webpack-loader",
// options: {
// bypassOnDebug: true,
// mozjpeg: {
// progressive: true,
// quality: 65,
// },
// // optipng.enabled: false will disable optipng
// optipng: {
// enabled: false,
// },
// pngquant: {
// quality: [0.65, 0.9],
// speed: 4,
// },
// gifsicle: {
// interlaced: false,
// },
// // the webp option will enable WEBP
// webp: {
// quality: 75,
// },
// },
},
],
},
},
],
},
};
(2)配置对比:
图片资源从 4.6MB 变为 2MB
,图片资源减少了57%
,图片个数由 110 个减为 42 个了,减少了68个
**这个是最合适的,最终也是采用了这个配置**