如何让网站的速度更快
做好每一个工作环节,更快,更稳定。
缩小文件加载体积
- 开启服务器 gzip 压缩,可以缩小文件传输体积
- 通过代码转译工具,可以缩小代码产出文件体积
- js 转译可以使用 terser
- css 转译可以使用 lightningcss
- html 压缩可以使用 html-minifier-next
- 文字、图片、视频,也都有相关的文件大小降低方案
- 文字加载可以使用 fontsource
- 图片压缩可以使用 https://tinypng.com/
- 视频压缩可以使用 ffmpeg 降低码率
降低初始运行时间
从打开网站,到用户看到可感知的内容,这段时间越快,就代表网站的打开速度越快。
如果你是一个偏图文的网站,内容可以放进 html 中,html 加载完成,用户就是可以阅读的,这样的加载感知是最快的。很多电商网站就是这样做的。
如果你需要在用户端获取并且展示额外数据,额外数据还很大的时候,那就需要告知用户,我需要你等。这个在游戏、重前端的应用中会比较常见。
降低性能开支
页面内容的渲染,是需要性能支持的。
在 html 页面画 1000 个基础 div 元素,可能感知不到等待时间,但是如果画 2000 个或者更多,就可以明显感知到页面渲染的等待时间了。
渲染内容过多是最常见的性能瓶颈点。
虚拟滚动
这类问题的第一个常见场景是表格。大量表格内容的快速渲染问题,有一个通用的解法,叫做虚拟滚动。
虽然单个表格需要呈现的内容非常多,会导致呈现等待时间很长,但是屏幕能够展示的内容是有限的。我可以选择计算屏幕当前需要展示哪些内容,只渲染这一部分内容,那就可以极大的降低呈现时间了。
这个做法通常可以让表格内容立即呈现,可接受的缺点是,在表格滚动过程中,性能开销会有所增加。
前端最常见的工具库是 react,在 react 中解决这个问题可以使用 react-virtualized。
vscode 可以秒开三百万行的空白文件,他的编辑器也有用到这个方法。
图表
另一个常见场景是图表。图表的内容可能会非常细密,还可能伴随更新需求。通常会使用 canvas 来解决。
canvas 的特点是,输出一张位图,渲染速度很快,比 html 快很多,这在图表需求上是常见的解决办法。
最常见的图表库是 echarts,优势是功能稳定,需求支持丰富,使用简单,缺点是体积比较大。
新兴的图表库,比如 antv、 charts 看起来也不错
还有一个老牌图表库是 d3.js,功能强大,数据处理和交互性都非常强,但是上手会比较难。直接用来处理需求的话,对接手的人要求比较高。一些新出的图表库是基于这个来开发的。
从网络的方面优化加载
HTTP 103 响应
网络请求遵循请求 -> 响应的时序逻辑,遵循 html -> css、js -> 字体、图片 的代码执行流程。
那可以加快这个流程吗?有方法的,HTTP 的 103 Early Hints,可以在 HTML 的响应节点,提前告知需要获取哪些资源。本来有多个串联流程,现在优化成了两个串联流程,并且第二个流程的开始时间还提前了一些,自然是会快一点的。
但可惜 safari 不支持 preload,只支持 preconnect。
曾经还有一个类似做法, http2 service push 可以从服务器推资源,也能起到类似请求提前的效果。但是没办法应用客户端缓存,会造成带宽浪费,所以一般不会使用。
CDN 优化
资源可以分成多个部分,可以按照内容是否发生了变更,来更新 CDN。
完善的前端工程,通常由开源库和业务代码组成,两者的更新频率并不一样。如果能分开放置 CDN,就可以在业务代码更新的时候,开源库仍然使用之前的 CDN 缓存。这样就降低了需要从网络获取的资源,从而更快一点。
一个实际的问题举例
我就职于一家设备生产公司,公司的官网挂着茫茫多不同型号设备的宣传页面。曾经我也是一个迷信大公司流行技术的实习生,人家说 Next.js 是最佳实践,整一个!人家说 SSR 渲染快,也整一个。一切看上去都很美好。
随着公司规模的逐渐扩大,设备的页面也随之增多,我网站的访问量慢慢的变高了。然后我发现服务器总是会内存不足,我只能先增加内存,做一个把挂掉服务拉起来的守护进程,然后仔细检查我遇到的问题。
回顾一下我的业务场景和技术方案,我的展示内容其实没有动态需求,是可以做纯静态站的。运行 SSR 服务一个是会多花钱,一个是,他引入了不确定因素,可能因为服务器压力导致宕机。
我决定做改版,改成 SSG 生成静态文件,走 CDN 提供站点内容的方式。
第一个问题,旧的页面那么多,改一下都要设计组同事和业务方确认,没办法处理的。那怎么和新的页面并存呢?弄个服务器分流,按链接接到新旧两个项目里。
第二个问题,怎么能让老板理解我的成绩呢?我找了一个 web 自动化测试工具,用代码拉起浏览器,访问我的页面,检查从请求发起,到页面内容展示出来,需要的时间。访问量最高的是首页,改他。本地跑起来两个服务,用自动化工具重复访问两个服务的首页,对比时间差别。你别管快多少,反正是快了。
第三个问题,这个问题是通过服务崩溃发现的,那其他页面会存在类似的问题吗?这真的是一个需要关注的场景吗?可以加一个问题监控和追踪平台,保持持续关注,比如 sentry。
嗯,问题解决,下班!
有关于 IETF 各种关于 HTTP Cache 的定义,可以参考两个库的实现 https://github.com/kornelski/http-cache-semantics https://github.com/nodejs/undici 对着 undici 的 interceptor API 写一个 in-memory cache handler