1. webpack打包优化,分包,压缩
这里使用webpack5打包,会有一些新特性,比较好用。
- 开启持久化缓存加快构建速度,
- Tree Shaking:消除未使用的代码,减小文件体积,
- 在
splitChunks
中进一步详细分包,提取公共的模块,减少重复打包, - 使用压缩插件,压缩打包的体积。
2. 使用gzip压缩传输
Gzip压缩是一种压缩方式,针对文本文件时通常能降低2/3的体积,可以减少传输的负担。
HTTP协议中用头部字段Accept-Encoding
和 Content-Encoding
对「采用何种编码格式传输正文」进行了协定,请求头的Accept-Encoding
会列出客户端支持的编码格式。当响应头的 Content-Encoding
指定了gzip时,浏览器则会进行对应解压。
一般浏览器都支持gzip,所以Accept-Encoding
也会自动带上gzip
,所以我们需要让资源服务器在Content-Encoding
指定gzip,并返回gzip文件
3. 图片处理
- 使用雪碧图合并图片,通过css定位展示不同图片,减少浏览器请求次数。
- 优先级不高的图片使用懒加载,或者使用背景图
background-image
定位替代img
标签。 - 动态渲染,当页面快要到视口时再加载图片。
4. 减少cookie体积
减少请求头cookie的体积,加快请求速度。
5. 开启预解析功能,Prefetch、Preload
<link>
标签的rel
属性的两个可选值。
Prefetch
,预请求,是为了提示浏览器,用户未来的浏览有可能需要加载目标资源,所以浏览器有可能通过事先获取和缓存对应资源,优化用户体验。
Preload
,预加载,表示用户十分有可能需要在当前浏览中加载目标资源,所以浏览器必须预先获取和缓存对应资源。
6. 开启浏览器缓存
根据业务场景开启协商缓存或者强缓存策略。有以下优点:
- 减少冗余的数据传输
- 减少服务器负担
- 加快客户端加载网页的速度
- 强缓存特点: 当请求资源的时,如果是之前请求过的并使用强缓存,那么在过期时间内将不会发送本次请求向服务器获取资源,而是直接从浏览器缓存中获取(不管资源是否改动)。过期了将重新从服务器获取,并再次强缓存。 强缓存是利用http头中的
Expires
和Cache-Control
两个字段来控制的,Expires
是http1.0的规范,Cache-Control
是在http1.1中出现的,我们这里使用Cache-Control
示范。 - 协商缓存特点:当请求资源时,如果是之前请求过的并使用协商缓存,还是发送请求到服务器,服务器通过逻辑判断确认资源没有修改返回304状态码,那么本次的资源则是从缓存中获取;如果经过判断确认资源被修改过,则重新发送资源到客户端,并且客户端更新缓存。 主要涉及到两组header字段:
Etag
和If-None-Match
、Last-Modified
和if-modified-since
。
7. cdn加速
对于请求的第三方静态资源文件,使用cdn加速,减少请求时间。
8. 优化第三方插件体积,比如Ant-Design组件库,moment等
使用Webpack Bundle分析时,会发现,第三方组件库Ant-Design等占用很大部分的体积。
- 这里我们可以按需引入,不必全部导入。
- 打包时避把moment文件打包进来
js
// webpack plugins
plugins: [
// Ignore all locale files of moment.js
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
9. css样式优化
- 尽量不要使用
display:none
等这种来设置样式,会引发页面回流 - 尽量使用transform,而不要用top,left等布局属性,减少性能开销
- 避免使用table布局,避免频繁修改布局
- 针对不认同业务场景,使用一些比较友好的图片格式。
10. 懒加载
- 非一级页面可以使用路由懒加载
lazy
- 优先级不高的引入文件也可以使用异步加载, 在script的标签中加上
defer
11. webwork开启浏览器多线程处理
首先你要了解以下知识点:
- 区分进程和线程的区别 进程之间是不共享资源和地址空间的,所以不会存在太多的安全问题,而由于多个线程共享着相同的地址空间和资源,所以会存在线程之间有可能会恶意修改或者获取非授权数据等复杂的安全问题。
- 谷歌浏览器是多进程的架构模式,一个tab页面对应着一个独立的进程,因此每个tab页面都有其独立的渲染引擎实例,一个进程里面有很多线程,比如:
- GUI线程,渲染html,当页面发生重绘回流时执行,当js引擎脚本运行时,就处于被挂起的状态,发生页面堵塞。
- js引擎线程,跟GUI是互斥的。
- 定时触发器线程,定时器
setInterval
与setTimeout
所在线程,不在js线程里面,可以结合事件机制综合理解 - 事件触发线程,因为js是单线程的,所以队列中的事件都要排队等待js去处理。
- 异步http请求线程,基于XMLHttpRequest,返回状态发生改变,如果设有回调函数,异步线程就返回的状态变更事件放到js处理队列中等待处理。
- web-work线程的工作原理和作用
- web-work是浏览器为了解决js单线程处理问题的,开启多线程处理,work和主线程不在一个上下文环境,是一个独立的线程,无法跟主线程直接通信,无法直接访问window,document等对象,无法读取主线程所在网页的 DOM 对象。但是可以使用navigate和location对象,可以通过
XMLHttpRequest
对象发出ajax请求。Worker 线程有独立的内存空间,Message Queue,Event Loop,Call Stack 等,线程间通过postMessage
通信。 主业务文件中
- web-work是浏览器为了解决js单线程处理问题的,开启多线程处理,work和主线程不在一个上下文环境,是一个独立的线程,无法跟主线程直接通信,无法直接访问window,document等对象,无法读取主线程所在网页的 DOM 对象。但是可以使用navigate和location对象,可以通过
js
const work = new Works('./work.js')
//向webwork推送数据
work.postMessage('hello')
work.onmessage = event =>{
//取到web-work处理完的数据
console.log(event.data) //world
}
web-work.js文件的代码
js
this.onmessage = event=>{
console.log(event.data) //hello
// 这里处理业务逻辑
work.postMessage('world')
}
现在明白了为什么浏览器是多进程的?如果多个页面共享同一进程,就会造成一个页面崩了,别的页面也会受到影响,用户体验效果不好,所以每个页面是独立的进程,进程之间 不存在资源共享。当然,单进程会导致内存占用过大问题。
为什么js引擎线程执行,GUI线程就要被挂起了嘛?因为js是可以操作dom的,会导致GUI渲染线程前后得到的元素数据不一致。
明白为什么要用webwork了嘛?可以异步处理海量数据给到主线程,防止js线程处理海量数据逻辑时占用太长时间,阻塞页面渲染。
12. 使用http2请求
知道http2和http1的区别吗? 在HTTP1.1中是默认开启了Keep-Alive
,虽然解决了多次连接的问题,但是依然有两个比较严重的问题:
- 串行传输:在单通道传输的前提下,假设要传输10个文件,那么只能依次逐个传输,传输完第一个再传输第二个,以此类推;
- 连接数问题:HTTP/1.1 虽然默认开启
keep-alive
可以复用一部分连接,但域名分片等情况下仍然需要建立多个connection,耗费资源,给服务器带来性能压力。
http2采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。 在 HTTP/2 中
- 同域名下所有通信都在单个连接上完成
- 单个连接可以承载任意数量的双向数据流
- 数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。
这一特性,使性能有了极大提升:
- 同个域名只需要占用一个 TCP 连接,使用一个连接并行发送多个请求和响应,消除了因多个 TCP 连接而带来的延时和内存消耗
- 并行交错地发送多个请求和响应,两两之间互不影响
- 在 HTTP/2 中,每个请求都可以带一个 31bit 的优先值,0 表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。
说了那么多,http2有以下优点:
- 二进制分帧
- 首部压缩(header compression)
- 服务器推送(server push)
- 多路复用
- HTTP2协商机制
总结:前端性能优化就好比海绵里的水,挤挤总会有的,未完待续~