Web开发

首页 » 常识 » 常识 » Web前端性能优化思路
TUhjnbcbe - 2023/5/4 21:49:00
彭洋出诊时间和医院 http://www.victroncapital.com/tszl

本文旨在整理常见Web前端性能优化的思路,可供前端开发参考。因为力求精简,限于篇幅,所以并未详述具体实施方案。

常见的优化方向有:

缩短请求耗时;

减少重排重绘;

改善JS性能。

§1缩短请求耗时

§1.1优化打包资源

总体原则:减少或延迟模块引用,以减少网络负荷。

常用工具:

webpack

webpack-bundle-analyzer可视化分析工具

常用方法:

减小体积:减少非必要的import;压缩JS代码;配置服务器gzip等;使用WebP图片;

按需加载:可根据“路由”、“是否可见”按需加载JS代码,减少初次加载JS体积;

分开打包:利用浏览器缓存机制,依据模块更新频率分层打包。

其他方法

雪碧图:每个HTTP/1.1请求都是独立的TCP连接,最大6个并发,所以合并图片资源可以优化加载速度。HTTP/2已经不需要这么做了。

§1.2CDN加速

总体原则:通过分布式的边缘网络节点,缩短资源到终端用户的访问延迟。

常用工具:

CloudFlare

§1.3浏览器缓存

总体原则:避免重复传输相同的数据,节省网络带宽,加速资源获取。

常用工具:

Nginx

常用方法:

可以通过设置HTTPHeader来控制缓存策略,一般有如下几种。

强缓存

Expires:HTTP/1.0

Cache-Control:HTTP/1.1

协商缓存

ETag+If-None-Match

Last-Modified+If-Modified-Since

拿Etag举例,如果浏览器给的If-None-Match值与服务端给的ETag值相等,服务器就直接返回,从而避免重复传输数据。

Etag+If-None-Match示例

如果几个配置同时存在,则优先级为:Cache-ControlExpiresETagLast-Modified。

§1.4更高版本的HTTP

总体原则:使用高版本HTTP提升性能。

常用工具:

HTTP/2

HTTP/2较HTTP/1.1最大的改进在于:

多路复用:单一TCP连接,多HTTP请求,有Demo;

头部压缩:减少HTTP头体积;

请求优先级:优先获取重要的数据;

服务端推送:主动推送CSS等静态资源。

其他方法:

HTTP/3+

HTTP/3基于UDP,很多方面的性能改进。

§1.5WebSocket

总体原则:解决HTTP协议无法实时通信。

WebSocket是一条有状态的TCP长连接,用于实现实时通信、实时响应。

§1.6服务器端渲染(SSR)

总体原则:第一次访问时,服务器端直接返回渲染好的页面。

一般流程:

浏览器向URL发送请求;

服务器端返回“空白”index.html;

浏览器不能呈现页面,需要继续下载依赖;

加载所有脚本后,组件才能被渲染。

SSR流程:

浏览器向URL发送请求;

服务器端执行JS完成首屏渲染并返回;

浏览器直接呈现页面,然后继续下载其他依赖;

加载所有脚本后,组件将再次在客户端呈现。它将对现有View进行合并。

除了可以提升页面用户体验,还能应用于SEO。

§2减少重排重绘

不同的前端框架有一些差异,但整体思路是一致的,这里将以React举例。

§2.1减少渲染量

总体原则:不渲染未展示的部分。

常用工具:

react-window

react-loadable

JS或框架自带,如import()、React.lazy

常用方法:

虚拟列表:只渲染可见区;

惰性加载:无限滚动;

按需加载:页面只在切换过去时才加载,。

以虚拟列表举例,以下是使用react-window库,仅仅渲染了可见区的数据:

虚拟列表示例

§2.2减少渲染次数

总体思路:避免重复的渲染。

常用工具:

lodash

JS或框架自带

常用方法:

防抖与节流;

对于React函数组件来说,合理使用副作用,拆分无关联的副作用;

对于React类组件来说,可以使用shouldComponentUpdate或使用PureComponent来优化渲染;

利用缓存,如React.memo;

使用requestAnimationFrame替代setInterval执行动画。

§2.3缓存复杂计算

总体思路:避免重复计算。

常用方法:

对于React函数组件来说,可以使用useMemo缓存复杂计算值。

举例如下,memoizedValue需要经过复杂计算才能得到,此时就可以使用useMemo缓存,仅仅在输入参数发生变化时才重新计算,这样也就避免了使用该值的AComponent进行重复渲染。

§3改善JS性能

§3.1WebAssembly

总体原则:将复杂的计算逻辑编译为WebAssembly,避免JS类型推断过程的性能开销。

适用范围有限:

曾在网上看到,有人使用自顶向下非优化的斐波那契数列算法来举例,说WebAssembly比原生JS快一倍,实测之后似乎也没有。

在同一台机器测试,其中求第48个值的耗时如下:

C(Ubuntu+GCC):18s

JS(V8):32s

WebAssembly(V8+EMCC):39s

一种可能的猜想是,斐波那契计算中没有大量的类型推断,而且V8内部有一些优化机制,使得此处JS执行速度快于WebAssembly。

因此,并非所有场景都适用于WebAssembly,需要具体事情具体对待。

§3.2WebWorker

总体原则:多线程思想。

常用方法:

DedicatedWorkers,处理与UI无关的密集型数学计算:大数据集合排序、数据压缩、音视频处理;

ServiceWorker,服务端推送;

SharedWorker,Tab间通信。

JS语言在设计之初就是单线程异步模型,好处是可以高效处理I/O操作,但坏处是无法利用多核CPU。

WebWorker会启动系统级别的线程,可进行多线程编程,发挥多核的性能。

总结

优化前端性能的方向主要有:

缩短请求耗时

优化打包资源

CDN加速

浏览器缓存

更高版本的HTTP

WebSocket

服务器端渲染

减少重排重绘

减少渲染量

减少渲染次数

缓存复杂计算

改善JS性能

WebAssembly

WebWorker

1
查看完整版本: Web前端性能优化思路