您现在的位置是:首页 >技术杂谈 >性能优化之思路和分析网站首页技术杂谈

性能优化之思路和分析

带脑子的CV工程师 2024-06-18 00:01:02
简介性能优化之思路和分析

、优化思路

  1. 尽可能减少首屏必须资源的体积
  2. 尽可能提前首屏必须资源/接口的请求发起时机
  3. 延后+闲时预缓存非必要资源/请求

代码分离
https://webpack.docschina.org/guides/code-splitting/

动态导入
https://webpack.docschina.org/guides/code-splitting/#dynamic-imports

splitChunk
https://webpack.docschina.org/plugins/split-chunks-plugin/

预获取/预加载模块(prefetch/preload module)

bundle 分析(bundle analysis)

缓存

资源使用覆盖率

1. Scm build 并上传到 CDN

主要关注产物体积,常见的有

  1. 依赖重复打包
  2. 有没有 Treeshaking/按需引入
  3. 没有适当分包(例如所有的包都打包在一个 bundle。[contentHash].js 中,
    那么每次更新业务代码或更新依赖包版本都会使得 hash 值改变,每次发布后用户都必须重新下载所有资源
  4. 没有适当分包还会使得首屏访问时,下载很多非首屏必须的资源(检查资源使用覆盖率)
  5. 打包压缩、服务器 gzip

2. 请求 HTML 文档,等待 HTML 文档返回(可能有未登录重定向),此时处于白屏状态

  1. 主要关注 html 的返回耗时

3. HTML 下载完后 ,通过浏览器的预加载器推测出页面所需的资源并按特定顺序发起请求

  1. 资源请求发起顺序是否合理(必须资源尽快发起,非必须资源延后)

4. 从上往下,下载解析执行 HTML 文档的 head 标签,如果有 css/js ,将阻塞之后的资源的执行。

  1. 因为会堵塞后面的流程,所以这里的 css 和 js 最好是尽量精简,只加载首屏必须(检查资源使用覆盖率)
  2. 检查是否命中浏览器强缓存/协商缓存 ,每次更新代码重新部署后有多少资源仍然能命中缓存

5. 对 HTML 文档的 body 标签进行解析渲染,因为 SPA 项目中 index.html body

一般只有一个空的容器标签,所以页面依然是白屏 。
  1. 可以在 html 中直接打入 loading 组件 or 骨架屏的代码并在此阶段展示,白屏比较影响体验

6. 依次下载解析执行 body 标签中的 js 和 css 。界面依然白屏,直到 ReactDOM.render(, document.getElementById(‘root’)) 触发后,界面开始渲染大体外框(侧边栏/头部导航栏),并开始请求 UserInfo、UserAuth、AppInfo 等全局状态。

  1. 关注资源的请求发起时机以及是否是首屏必须资源
  2. 一些接口可以预取, 接口获取权限数据,并且在获取权限数据前会阻塞组件渲染。
    因此我们可以把该接口请求时机提前,能有效提升体验。 推荐的预取方式是 Link preload

7. 进入 react-router,如使用了代码分割动态加载

8. 调用 API 获取到业务数据后,填充进页面,展示出最终的页面内容。

  1. 一般到这就是 LCP 和 TTI 的时间点,我们的优化目标就是把这个时间点提前

三、产物分析

在众多性能优化项中,产物体积优化是最容易拿到性能收益的一项。
移除页面上的非必须资源不仅能减少网络传输时间, 
也能减少 CPU 的解析/编译时间和潜在的内存开销。

社区有挺多开源的分析工具:

  • webpack-chart: webpack stats 可交互饼图。
    https://alexkuz.github.io/webpack-chart/

  • webpack-visualizer: 可视化并分析你的 bundle,检查哪些模块占用空间,哪些可能是重复使用的。
    https://chrisbateman.github.io/webpack-visualizer/

  • webpack-bundle-analyzer:一个 plugin 和 CLI 工具,
    它将 bundle 内容展示为一个便捷的、交互式、可缩放的树状图形式。
    https://github.com/webpack-contrib/webpack-bundle-analyzer

  • webpack bundle optimize helper:这个工具会分析你的 bundle,
    并提供可操作的改进措施,以减少 bundle 的大小。
    https://webpack.jakoblind.no/optimize/

    • bundle-stats:生成一个 bundle 报告(bundle 大小、资源、模块),
      并比较不同构建之间的结果。
      https://webpack.docschina.org/api/stats/

优化案例

https://www.cnblogs.com/cczlovexw/p/14187645.html
https://loadable-components.com/docs/code-splitting/
重复打包
按需加载
webpack拆分最正确的办法
https://david-gilbertson.medium.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758

运行时分析

  1. chrome devtools performance
    https://developer.chrome.com/docs/devtools/performance/
    https://developer.chrome.com/docs/devtools/performance-insights/

  2. 覆盖率
    https://developer.chrome.com/docs/devtools/coverage/

  3. lighthouse会同时记录上面的performance和覆盖率报告
    https://developer.chrome.com/docs/devtools/lighthouse/

  4. 起一个好的chunk name
    https://www.codemzy.com/blog/how-to-name-webpack-chunk

运行时分析最好能做到控制变量。 chrome 提供了限制网速的选项,
但是对于 cpu 性能只提供了按倍速限制的能力(用于模拟移动端性能)

  1. 先从 pv 最高、tti 也比较高的页面开始
  2. 用 chrome 无痕模式
  3. 网络情况:
  4. 停用缓存 (可选)测试页面在无浏览器缓存情况下的加载性能时可以打开
  5. 限速(要小于你的最小网速,不然就没意义了)

、requestAnimationFram

requestAnimationFrame 是浏览器专门为动画提供的 API,
它的刷新频率与显示器的频率保持一致,
使用该 api 可以解决用 setTimeout/setInterval 制作动画卡顿的情况

Web Worker 优化长任务

由于浏览器 GUI 渲染线程与 JS 引擎线程是互斥的关系,
当页面中有很多长任务时,
会造成页面 UI 阻塞,出现界面卡顿、掉帧等情况


	要考虑 web worker的通信时长
 Time 是这个资源的通信时长(也叫加载时长)

proformance火焰图

在这里插入图片描述
在这里插入图片描述


每个资源请求的图形中都存在一左侧线段、浅色矩形、深色矩形、右侧线段:
左侧线段:Request Sent 之前所有时间花费(Queueing ~ Proxy negotiation)。
浅色矩形:Request Sent + Waiting (TTFB)。
深色矩形:Content Download。
右侧线段:等待主线程的时间花费。

一些关注点:

资源的优先级和耗时。鼠标悬浮到对应资源上可以看到资源优先级(Highest、High、medium、Low、Lowest)。

检查是否有 Highest 的非关键资源,或者是否存在某些关键资源以 Low、Lowest 优先级进行加载;

资源加载各阶段耗时。资源矩形的长度体现了耗时,鼠标悬浮到对应资源上可以看到具体耗时和时间组成。
检查是否存在耗时较长的资源、队列或主线程等待时间是否符合预期、是否影响到其他关键资源。

加载顺序。某些关键资源的请求路径较深,是否可以提前加载,详见预加载关键资源。

资源开始加载、完成、执行的时机(FP、FCP、LCP...)是否符合预期。

关键资源耗时,在 Network 的瀑布图可以做更具体的耗时分析

Queueing:队列等待时间。以下情况下请求会进行排队:

存在更高优先级的请求;


同源仅能打开六个 TCP 连接的限制(仅适用于 HTTP/1.0 和 HTTP/1.1);

浏览器需要在磁盘缓存中短暂分配空间。

Stalled:请求停滞。请求可能因排队中所述的任何原因而停止。

DNS Lookup:DNS 查找。浏览器正在解析请求的 IP 地址。

Initial connection:初始连接。浏览器正在建立连接,包括 TCP 握手/重试和协商 SSL.

Proxy negotiation:代理协商。浏览器正在与 proxy server 协商请求。

Request sent:请求已发送。正在发送请求。

ServiceWorker Preparation: ServiceWorker 准备。浏览器正在启动 Service Worker。

Request to ServiceWorker: 请求 ServiceWorker。请求正在发送给 service worker.

Waiting (TTFB): 等待(TTFB,Time To First Byte)。
浏览器正在等待响应返回的第一个字节,此时间包括 1 次往返延迟和服务器准备响应所用的时间。

Content Download:内容下载。浏览器直接从网络或 Service Worker 接收响应。

Content Download 表示读取响应内容所花费的总时间。大于预期的值可能表示网络速度较慢,
或者浏览器正忙于执行其他工作,从而延迟了响应的读取。

Receiving Push:接收推送。浏览器正在通过 HTTP/2 服务器推送接收此响应的数据。

Reading Push: 读取推送。浏览器正在读取之前接收到的本地数据。

参考链接
掘金地址点击查看

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。