优化具体指的什么
我们经常说起前端优化,作为一个小白,其实有很多疑惑,什么优化,怎么优化,实在常常有种无从下手分析的感觉。
想起一个经典的问题:输入url到浏览器呈现,中间经历了什么?
1、浏览器进行URL解析和生成HTTP请求
2.生成TCP报文段,准备发起TCP连接
3.DNS解析域名得到服务器的IP地址
4.IP路由寻址和生成IP数据报
5.ARP请求下一跳网关MAC地址
6.报文经过网络发往WEB服务器
7.服务器返回响应报文
8.浏览器解析渲染
上面这个问题的答案应该也就解释了我们要关注的优化点:
- 网络请求优化。
- 首屏加载优化。
- 渲染过程优化。
- 计算/逻辑运行提速。
下面就从这四个优化方向展开说说
网络请求优化
网络请求优化的目标在于减少网络资源的请求和加载耗时,如果考虑 HTTP 请求过程,显然我们可以从几个角度来进行优化:
- 请求链路:DNS 查询、部署 CDN 节点、缓存等。
- 数据大小:代码大小、图片资源等。
对于请求链路,核心的方案常常包括使用缓存,比如 DNS 缓存、CDN 缓存、HTTP 缓存、后台缓存等等,前端的话还可以考虑使用 Service Worker、PWA 等技术。使用缓存并非万能药,很多使用由于缓存的存在,我们在功能更新修复的时候还需要考虑缓存的情况。除此之外,还可以考虑使用 HTTP/2、HTTP/3 等提升资源请求速度,以及对多个请求进行合并,减少通信次数;对请求进行域名拆分,提升并发请求数量。
数据大小则主要考对请求资源进行合理的拆分(CSS、Javascript 脚本、图片/音频/视频等)和压缩,减少请求资源的体积,比如使用 Tree-shaking、代码分割、移除用不上的依赖项等。
在请求资源返回后,浏览器会进行解析和加载,这个过程会影响页面的可见时间,通过对首屏加载的优化,可有效地提升用户体验。
首屏加载优化
首屏加载优化核心点在于两部分:
- 将页面内容尽快地展示给用户,减少页面白屏时间。
- 将用户可操作的时间尽量提前,避免用户无法操作的卡顿体验。
减少白屏时间除了我们常说的首屏加载耗时优化,还可以考虑使用一些过渡的动画,让用户感知到页面正在顺利加载,从而避免用户对于白屏页面或是静止页面产生烦躁和困惑。除了技术侧的优化,很多时候产品策略的调整,给用户带来的体验优化效果不低于技术手段优化,因此我们也需要重视。
整体的优化思路包括:尽可能提前页面可见,以及将用户可交互的时间提前。一般来说,我们需要尽可能地降低首屏需要的代码量和执行耗时,可以通过以下方式进行:
- 对页面的内容进行分片/分屏加载
- 仅加载需要的资源,通过异步或是懒加载的方式加载剩余资源
- 使用骨架屏进行预渲染
- 使用差异化服务,比如读写分离,对于不同场景按需加载所需要的模块
- 使用服务端直出渲染,减少页面二次请求和渲染的耗时
有些时候,我们的页面也需要在客户端进行展示,此时可充分利用客户端的优势:
- 配合客户端进行资源预请求和预加载,比如使用预热 Web 容器
- 配合客户端将资源和数据进行离线,可用于下一次页面的快速渲染
- 使用秒看技术,通过生成预览图片的方式提前将页面内容提供给用户
除了首屏渲染以外,用户在浏览器页面过程中,也会触发页面的二次运算和渲染,此时需要进行渲染过程的优化。 首屏加载优化核心点在于两部分:
- 将页面内容尽快地展示给用户,减少页面白屏时间。
- 将用户可操作的时间尽量提前,避免用户无法操作的卡顿体验。
减少白屏时间除了我们常说的首屏加载耗时优化,还可以考虑使用一些过渡的动画,让用户感知到页面正在顺利加载,从而避免用户对于白屏页面或是静止页面产生烦躁和困惑。除了技术侧的优化,很多时候产品策略的调整,给用户带来的体验优化效果不低于技术手段优化,因此我们也需要重视。
整体的优化思路包括:尽可能提前页面可见,以及将用户可交互的时间提前。一般来说,我们需要尽可能地降低首屏需要的代码量和执行耗时,可以通过以下方式进行:
- 对页面的内容进行分片/分屏加载
- 仅加载需要的资源,通过异步或是懒加载的方式加载剩余资源
- 使用骨架屏进行预渲染
- 使用差异化服务,比如读写分离,对于不同场景按需加载所需要的模块
- 使用服务端直出渲染,减少页面二次请求和渲染的耗时
有些时候,我们的页面也需要在客户端进行展示,此时可充分利用客户端的优势:
- 配合客户端进行资源预请求和预加载,比如使用预热 Web 容器
- 配合客户端将资源和数据进行离线,可用于下一次页面的快速渲染
- 使用秒看技术,通过生成预览图片的方式提前将页面内容提供给用户
除了首屏渲染以外,用户在浏览器页面过程中,也会触发页面的二次运算和渲染,此时需要进行渲染过程的优化。
渲染过程优化
渲染过程的优化要怎么定义呢?我们可以将其理解为首屏加载完成后,用户的操作交互触发的二次渲染。
主要思路是减少用户的操作等待时间,以及通过将页面渲染帧率保持在 60FPS 左右,提升页面交互和渲染的流畅度。包括但不限于以下方案:
- 使用资源预加载,提升空闲时间的资源利用率
- 减少/合并 DOM 操作,减少浏览器渲染过程中的计算耗时
- 使用离屏渲染,在页面不可见的地方提前进行渲染(比如 Canvas 离屏渲染)
- 通过合理使用浏览器 GPU 能力,提升浏览器渲染效率(比如使用 css transform 代替 Canvas 缩放绘制)
以上这些,是对常见的 Web 页面渲染优化方案。对于运算逻辑复杂、计算量较大的业务逻辑,我们还需要进行计算/逻辑运行的提速。
计算/逻辑运行提速
计算/逻辑运行速度优化的主要思路是“拆大为小、多路并行”,方式包括但不限于:
- 通过将 Javscript 大任务进行拆解,结合异步任务的管理,避免出现长时间计算导致页面卡顿的情况
- 将耗时长且非关键逻辑的计算拆离,比如使用 Web Worker
- 通过使用运行效率更高的方式,减少计算耗时,比如使用 Webassembly
- 通过将计算过程提前,减少计算等待时长,比如使用 AOT 技术
- 通过使用更优的算法或是存储结构,提升计算效率,比如 VSCode 使用红黑树优化文本缓冲区的计算
- 通过将计算结果缓存的方式,减少运算次数
以上便是时间维度的性能优化思路,还有空间维度的资源优化情况。
上面主要对优化的模块,进行了区分,在项目实际开发中,具体优化的点,应该还是从全链路检测页面打开,确定耗时的位置。现在常用的webpack5基本上已经对打包的文件做了tree-shaking,split-bundle已经都带上了。如果使用webpack5所以打包的优化,感觉空间不是特别大,网络请求的这块优化可能更多的还是从cdn入手。剩下的就是结合业务进行深度优化,比如,页面打开,核心区域的展示,这些与具体的业务深入结合。