跳到主要内容

白屏优化方案

· 阅读需 6 分钟

指标

FCP(First Contentful Paint):白屏时间(第一个文本绘制时间)

Speed Index:首屏时间

TTI(Time To Interactive): 第一次可交互的时间

lighthouse score(performance):Chrome浏览器审查工具性能评分(也可以npm install -g lighthouse,编程式调用)

打包产物优化

  1. tree shaking

清除未使用的代码

Vite: 只要遵循 ESM,Vite 自动树摇优化

Webpack:mode 改为 production;babel 的 modules 改为 false,不要转为 cjs;启用 optimization 的 usedExports 选项

  1. 代码压缩

Vite 自动压缩 css,js 可以靠 terser 插件来处理,rollupOptions.plugins 配置,例如删除 clg 和注释

Webpack 靠 loader 和插件,例如 css-loader-minimizeTerserPlugin,UglifyJsPlugin

  1. 分包

Vite: build.rollupOptions.output.manualChunks

Webpack: optimization.splitChunks

不怕包多,因为 http2 多路复用

  1. 排查冗余依赖、静态资源

传输(网络/请求)优化

  1. 开启 http2
server {
listen 443 ssl http2; # 启用 HTTPS 和 HTTP/2
server_name yourdomain.com;

ssl_certificate /path/to/your/cert.pem;
ssl_certificate_key /path/to/your/key.pem;

location / {
proxy_pass http://backend_service; # 后端服务地址
proxy_http_version 1.1; # 继续使用 HTTP/1.1 与后端通信
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
  1. gzip 压缩传输

nginx 配置 gzip

#开启和关闭gzip模式
gzip on;
#gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 6;
# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;
# nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;
  1. prefetch preload

<link> 标签的 rel 属性的两个可选值。 Prefetch,预请求,是为了提示浏览器,用户未来的浏览有可能需要加载目标资源,所以浏览器有可能通过事先获取和缓存对应资源,优化用户体验。 Preload,预加载,表示用户十分有可能需要在当前浏览中加载目标资源,所以浏览器必须预先获取和缓存对应资源。

首屏字体、大图加载,CSS中引入字体需要等CSS解析后才会加载,这之前浏览器会使用默认字体,当加载后会替换为自定义字体,导致字体样式闪动,而我们使用Preload提前加载字体后这种情况就好很多了,大图也是如此

类似字体文件这种隐藏在脚本、样式中的首屏关键资源,建议使用preload

Vite: 用插件

Webpack: 注释 /* webpackPrefetch: true */

  1. cdn 内容分发网络

将静态资源托管到 cdn,就近派发

图片优化

  1. 图标优化

雪碧图:将多张比较小的图片,合并到一张大的图片上面,大的图片背景透明,使用的时候通过不同的 background-position定位来展示的那部分图片。

iconfont

svg:将图片转换为svg文件,一个 svg 文件可能会存在若干图标

  1. 小图变成 dataUrl

Vite 自带

Webpack:使用 url-loader

  1. thumbnail

图片不用原图,而是使用分辨率低的小图占位

  1. 懒加载

对于图片很多的情况下,可以使用 Intersection Observer 、模糊图作为 div 父元素的背景等懒加载方案

交互优化

  1. loading 首屏和路由跳转

通常会在 index.html 上写简单的 CSS 动画,直到应用挂载后替换挂载节点的内容

  1. 骨架屏

代码优化(React)

针对使用 antd 的 ProTable 组件的页面进行优化,主要方案如下

  1. 减少 State

检查代码行文逻辑,尤其是 request 中的清理或重置状态的逻辑

可以使用 if 减少无意义的 setState

  1. 使用 setEditableKeys(ids) 替代 action?.startEditable(id)

  2. 减轻表格渲染压力:只负责展示文本

  3. 利用缓存减少数据处理过程(空间换时间)

使用 useRef 存储数据处理结果,作为后续处理过程的参考或者恢复时的备份

尽可能将多个需求的数据处理过程合并,减少时间复杂度

  1. 虚拟滚动

  2. 使用 useMemo 处理 tableComponents

当需要重写 table 的组件例如 cell 或者 body 时,可以使用 useMemo 缓存这个组件,减少不必要的计算与更新

使用 useCallback 缓存复杂回调函数,对于作为回调函数传入 memo 组件的函数,非常好用

  1. columns 配置中适当添加 shouldCellUpdate

  2. 避免使用第三方高度封装的组件。。例如 EditableProTable