项目中的图片处理和图片预加载
1.问题
在项目中,如果包含了太多图片等静态资源,那么打包后的文件会非常大,如果不进行一些处理,会导致非常糟糕的浏览体验。
2.解决
1.图片压缩
这里联我想到的第一种方法就是压缩静态资源的大小,像很多正式项目比如:微信、钉钉、b站等等都会自动压缩图片视频。
图片视频的压缩可以使用下面三个工具:
- TinyPNG : 傻瓜式操作,一键压缩,画质不变
- squoosh : 简单好用的在线图片压缩工具,可选画质、尺寸等参数
- img-compressor : 一个简单高效的JS图片压缩库,项目中有上传图片的,可以控制图片体积,就像微信钉钉一样
但这种方法在图片较多时,效果有限,无法从根本上解决问题。
2.图片云存储
第二种方法就是将图片等资源上传到云上,然后再使用外链的方式引入。
这种方式也是在实际开发中较为常用的方法,一般都是将图片上传到服务器(例如:OSS)上,然后在页面中通过 url 的形式引入图片。
但这种方式仍然需要先下载后加载,而下载速度较慢时,仍然会导致用户体验糟糕,例如图片未加载时,出现白屏的现象。
这样就引出了图片预加载的需求。
3.图片预加载
对于一个项目,其会有首屏的概念,即进入项目后的第一个页面。
而图片预加载就是在首屏加载完毕后,预先加载其它页面所需的图片,这样,切换到该页面时,浏览器就不需要再去请求该图片,直接渲染即可。
那么,如何实现?
以一个vue项目为例,在首页加入以下内容:
// 请求后端,获取url列表
const getUrls = async (data) => {
let res = await getUrlsFormSer(...data);
return res.result.urlList
}
// 预加载的方法
const preLoadImgs = (urlList) => {
urlList.keys().forEach(key => {
new Image().src = urlList(key)
})
}
// 在组件创建完毕后,进行预加载
created(() => {
// 在window.onload完毕后,开始预加载图片
window.onload = () => {
let urlList1 = getUrls(data1);
let urlList2 = getUrls(data2);
let urlList3 = getUrls(data3);
...
preLoadImgs(urlList1);
preLoadImgs(urlList2);
preLoadImgs(urlList3);
...
}
})
注意点:
- 预加载的关键点:
new Image().src = xxx
,这个操作相当于给浏览器缓存了图片的路径!所以可以达到预加载的效果,后续在其它页面中直接使用 url 引入时加载会更快,因此不会出现白屏的现象。 - 执行时机:在首屏的
window.onload
完毕后,进行预加载。因为首屏包含的图片无需预加载,window.onload
意味着文档及图片加载完毕,也就是说,首屏加载完毕时才会去执行上述的图片预加载代码。 - 如果将大量的图片都进行预加载,可能会阻塞后续的任务!
总结
适当的预加载图片可以提升用户体验,但它不会提高网站的性能!
如果要提升网站性能,可以使用下面的两种方法。
1.懒加载
HTMLImageElement.loading : 图片可以通过设置loading
属性值为lazy
的方式,实现图片的懒加载(图片仅在马上要出现在可视视口中时开始加载)
<img src="@/assets/images/tech-3.png" loading="lazy"/>
2.延迟加载
首屏的加载速度至关重要,当首页的图片过多时,可以只加载首屏可见区域的图片,其它延迟加载!