在前端中性能优化的点主要分为两个阶段:
初始阶段:
主要就是加载方面优化的问题。所有问题的指导原则就两点:
- 尽可能的减少前端资源的数量
- 尽可能的减小前端资源的大小
运行阶段:
主要就是渲染方面优化的问题。只要是在浏览器中,所有的问题的指导原则就是:
- 尽可能的减少操作 DOM
-
首页加载慢优化:
通过懒加载的方式处理非首屏的图片;
对于小图标可以采用 iconfont 的方式解决;
对于小图片可以采用雪碧图的方式解决。 -
减少请求量:
1.合并资源:减少 HTTP 请求数,通过ngix服务器做资源合并, 将多个JavaScript、CSS请求合幵成一个,静态文件来减少http请求,可以在一定程度上能减少web服务器的压力。
例如:http://example.com/??style1.css,style2.css,foo/style3.css?v=102234
(一次请求就拿到三个样式文件)
2.通过打包工具(Webpack)来做资源文件的物理打包(相对没有第一种灵活);
3.在代码层面,对于需要引入一些大型第三方库时,可以通过特定的 Babel 插件来进行按需加载;
4.进行前端路由层面的懒加载,从而可以减少首页的 JS 和 CSS 的大小。 -
减少资源大小
1.可以通过压缩和混淆加密来减小文件体积;
2.图片则可以使用工具来压缩、去除元数据(比如拍照日期)、base64转码,使用 webp 格式;
3.同时可在服务器端开始 gzip 压缩来最大化减少所有文件体积。
4.减少cookie数据量 -
加快请求速度:
1.预解析 DNS,减少域名数,并行加载,使用内容发布网络(CDN)。
2.使用http2通信
a.http2会进行头部压缩;
b.二进制帧方式传送,http1使用的字符串,不好处理;二进制会使数据确认、处理速度快速,出错率低。
c.链路复用:之前http1请求发出去之后在服务器进行处理时候,这条建立起来的链接处于空挡状态。链接在,但是没发送数据,http1时这条路别人也不能用。但是http2就可以用,好处:不用重复建立链接,可以发送更多的数据。每个 request 请求可以随机的混杂在一起,接收方可以根据 request 的 id 将 request 再归属到各自不同的服务端请求里面。
hhtp2中最好不要做资源合并和域名分片。
注: CDN 之所以能够加速,是因为会在很多地方都部署 CDN 服务器,如果用户需要下载静态资源,会自动选择最近的节点下载;
同时由于 CDN 服务器的地址一般都跟主服务器的地址不同,所以可以破除浏览器对同一个域名发送请求的限制(http1.0同一域名下只能发送6个请求) -
实现 Webpack 打包优化
可以通过设置 mode = production 默认实现 Webpack 对代码的混淆和压缩,最大程度减少代码体积;
并且可以设定一些打包策略,并配合网络缓存做最终的加载性能优化。
注:网络缓存:
HTTP 协议缓存请求,添加本地缓存。
对于不需要经常变动的资源(第三方包),可以使用Cache-Control: max-age=31536000
(缓存一年) 并配合协商缓存ETag
使用(一旦文件名变动才会下载新的文件)
对于需要频繁变动的资源(代码包),可以使用Cache-Control: no-cache
并配合ETag
使用,表示该资源已被缓存,但是每次都会发送请求询问资源是否更新。
具体可以看我前面的协商缓存和强缓存一文。
缓存机制
打包策略优化(使用webpack中splitChunks进行):通常分为两类:
第三方库包分成一个包;
自己实现的代码放在src中:其中一些公共的组件和非公共的组件也可以分开。这样每次加载时只有进入相应的路由(前端使用路由懒加载),对应的包才会进来进行,实现按需加载,减少请求的资源大小。 -
渲染:
- 可以使用 document.createDocumentFragment 创建虚拟节点,从而避免引起没有必要的渲染;
- 当所有的 li 都创建完毕后,一次性把虚拟节点里的 li 标签全部渲染出来;
- 可以采取分段渲染的方式,比如一次只渲染一屏的数据;
- 最后使用 window.requestAnimationFrame 来逐帧渲染;
- 使用服务端渲染。