如果一个网页中包含比较多的图片,在页面加载时,会严重拖慢整个页面的加载速度,这就是我们今天要解决的问题.
这篇文章聊一下如何去优化图片,提高页面的加载速度。文章中演示的例子,只是将几张大图片简单的展示出来,通过这个例子去展示如何优化.
例子的源码在 github.com/XYShaoKang/… 中,可以克隆到本地进行调试,在线预览地址 xyshaokang.github.io/image-optim…
先看下优化前后的对比:
上面一个是优化前的,下面是优化后的,为了对比效果,将速度限制为
10Mbit/s
可以看很明显的对比,优化前需要将近 20s 的时间,而优化后只用了不到 1s 的时间
接下来介绍是如何一步步优化的
# 生成不同尺寸的图片
在页面中展示的图片一般都比需要展示的宽度要大,比如一张 1080px 宽的图片,可能只需要展示在 400px 的框内,没有必要直接使用原图,可以使用原图生成一张 400px 宽的图片,这样可以在不损失画质情况下节省带宽,提升加载速度.
另外很多时候我们需要做响应式布局,可能在一种布局下,需要展示 200px 宽度的图片,而在另外一种布局下,需要展示 600px 宽度的图片,这个时候就需要生成多种尺寸的图片.
所以我们可以提前定义一些尺寸范围的预设,将所有图片生成生成预设中对应尺寸的图片,然后在使用时根据实际要展示的宽度,去加载对应范围宽度的图片.
在例子中我所使用的预设
const widths = [40, 200, 400, 800, 1200, 1600] |
然后使用 sharp 生成指定尺寸的图片
/** | |
* 生成指定宽度的图片 | |
* @param input 原图路径 | |
* @param output 目标路径 | |
* @param width 目标宽度 | |
* @returns | |
*/ | |
function resizeImage(input: string, output: string, width: number) { | |
return sharp(input).resize(width).toFile(output) | |
} |
如果有将代码克隆到本地,可以运行
pnpm cli
(如果是 npm 使用npm run cli
, 如果是 yarn 可以使用yarn cli
) 来查看实际生成的图片,生成的图片在dist/image
详细源码,可以查看 cli.ts
# 通过设置 img 的 srcSet 属性来根据不同的宽度使用对应大小的图片
srcSet 是以逗号分隔的多个字符串表示可用的图像,每个字符串是由空格分隔的前后两部分,后面是当满足条件时使用这个图片,前面则是图片的地址,关于 srcSet 更具体的描述,可以查看 MDN 中的介绍 img: srcset
这里我们指定预设好的尺寸以及对应的链接,这样在加载时,会根据当前展示图片需要的宽度,加载对应尺寸的图片.
const Image: FC = () => { | |
const srcSet = `image/cat-young-animal-curious-wildcat-200.jpg 200w, | |
image/cat-young-animal-curious-wildcat-400.jpg 400w, | |
image/cat-young-animal-curious-wildcat-800.jpg 800w, | |
image/cat-young-animal-curious-wildcat-1200.jpg 1200w, | |
image/cat-young-animal-curious-wildcat-1600.jpg 1600w` | |
return <img srcSet={srcSet} /> | |
} |
实际效果,可以看到随着需要展示的图片不断变大,浏览器会加载我们在 srcSert 中定义的对应的图片.
# 渐进式加载
如果需要展示的图片的宽度比较大时,需要加载比较大尺寸的图片,可能需要一些时间加载,图片的位置就会显示白色,体验比较差。可以通过渐进式加载的方式让体验变的更好.
具体的做法是,不直接去加载大尺寸的图片,而是先加载一个小尺寸的图片 (比如我们上面预设的尺寸中 40px 宽的图片就派上用场了), 然后将小图片放大充当图片的占位符 (小尺寸图片可以很快加载完成,这时页面是已经有图片,虽然比较糢糊,但至少会比一块空白让用户体验更好), 然后在后台加载大尺寸的图片,等加载完成之后,将小图片替换成大图片.
通过设置 filter: blur(20px);
可以让小图像看起来不至于都是像素点,反而有一丝朦胧的感觉.
在加载完成时,加上一点糢糊的过度,图片从糢糊慢慢变清晰的过程,符合用户在等待过程中,希望图片逐渐被下载的预期.
图片组件的详细源码请查看 Image.tsx
# 懒加载
懒加载是通过延迟不可见图片的加载,从而避免不必要的下载.
要实现懒加载,只需要在 img 标签加上 loading="lazy"
即可开启原生支持的懒加载.
不过什么样的图片会延迟加载,什么情况下回去加载图片,需要看浏览器具体的实现。更多信息可以看后面的参考资料
# 后记
本篇文章讲解了如何一步步去优化网页中的图片,优化的步骤:
- 生成不同尺寸的图片
- 通过 sharp 来生成预设尺寸的图片
- 通过设置 img 的 srcSet 属性来根据不同的宽度使用对应大小的图片
- 渐进式加载
- 生成小图片用作占位符
- 糢糊图片 blur
- 图片懒加载
当然还有其他可以优化的点,比如调整 sharp 的参数输出更小的图片,以及压缩率更高的图片,通过 CDN 来提升图片的下载速度等等,感兴趣的同学可以自行深入研究.
本文主要是研究 gatsby-plugin-image 如何实现的过程中,总结而来.
# 参考资料
- gatsby-plugin-image
- The “Blur Up” Technique for Loading Background Images
- Why You Should Use Picture Tag Instead of Img Tag
- Responsive images
- Progressive loading
- 延迟加载
转自:https://juejin.cn/post/7033780851053690894