- 苏格团队
- 做者:Jason
因为业务的须要,笔者最近须要实现一个大量图片同时加载的需求。在实现这个需求的过程当中,笔者遇到了不少的坑,也总结了一些优化方案。这里将笔者使用或准备使用的优化方案总结一下。前端
在描述如何解决问题,咱们如今先来申明,问题是什么? 笔者的需求大概是在某个页面显示 1~1000张,200~500k大小的图。好消息是这些图片来源于本地硬盘而非网络。(不然这个问题就要变成优化网络....)promise
因为不是纯前端的项目,笔者能够从本地文件夹中读取文件。而后一段代码劈里啪啦的就出现了。缓存
const fileList = this.props.fileList;
return (
<div className="list-wrapper">
{
fileList.map((file) => {
<img className="img-item" src={file.src}>
})
}
<div>
)
复制代码
就在笔者满心欢喜的认为这个需求基本搞定了,该去楼下加鸡腿的时候。无情的现实狠狠的抽了我一巴掌。随着网页的刷新,一张纯白的画面展现在了个人面前,而后只见图片一点一点的从上面加载出来。 我不由陷入了沉思,是CPU跑不动道了仍是内存飘了?在一想,我这电脑都这个表现,真要上线了,这客户能忍受吗?不对,就这表现,没上线前产品小姐姐就的把我ko了...bash
这种场景下想必你们第一反应也是懒加载。 简单介绍一下图片懒加载。常见的图片懒加载方案是指页面加载时只渲染屏幕可见区域及周围的图片。当页面滚动时再加载须要显示的图片。
出于提升效(tou)率(lan)的目的,笔者在网上找了个比较好用的懒加载库而后引入项目。 然而,状况并不乐观。由于该需求场景下每一张图片的宽高都是 50*50,那么在PC端常见的 1080p 的设备上首屏须要显示的图片达到了400+张。
即使咱们忽视这个问题,当用户滚动网页速度很快时图片加载的体验也是不ok的。因此懒加载并非万能的。服务器
首先咱们要知道,在硬件性能不变且CPU调度不能更积极的前提下。理论上咱们没法减小图片渲染的时间。因此咱们只能想办法调整图片渲染的方式来提升用户的体验。 因此咱们采用预加载的方式。网络
const fileList = this.props.fileList;
fileList.forEach((element) => {
let img = new Image();
img.src = element.src;
img.onload = () => {
// 渲染这张图
...
}
})
复制代码
固然咱们也可使用img.decode()方法对图片进行解码,它会返回一个promise对象。app
img.decode().then(() => {
// 渲染这张图
...
})
复制代码
采用了这套方案后,图片会一张又一张的加载。然而,加载的速度实在是不敢恭维。若是用户想看最后那张图片,那他只能在哪里进行长久的等待...性能
众所周知,3 = 1 + 2。 因此方案三就是方案一和方案二的结合体。 首先咱们加载一张图片未加载时的底图(占位)。然后咱们继续采用方案二的方式进行图片逐个的预加载。 当用户滚动图片时,咱们便改变下一站预渲染的图片为用户可见区域的第一张。 然而,状况仍是不乐观。当用户的滚动条匀速直线不停的往下运动时,效果依然不好。优化
综合上面几种方案,基本能优化的咱们都已经优化了。那如继续何提升用户的体验呢?彷佛,咱们只能从图片自己去下手?
上文也提到,在我所面临的需求场景下一张图片的显示宽高为50 * 50。 而图片的大小为200~500k。因此咱们能够采用缩率图的方式,先渲染一张3~5k大小的缩略图,等用户点击图片查看详情时再去渲染大图。 采用缩略图的状况下咱们再使用方案三进行优化,性能表现几乎就能够知足这个场景下用户的需求了。ui
固然,上面的几种优化方案只是我在某个项目中使用。咱们仍然能够采用例如图片渐进式加强,CDN缓存,图片压缩,设立单独的资源服务器等诸多方式。图片的加载优化自己也是一个前端老生常谈的问题,业内已经有太多太多的解决方案。若是你有更好的方案,你也能够在下面留言告诉我。谢谢观看。