1. 概念简介
目前检测web页面性能常用的工具是浏览器(侧重Chrome)开发工具里的性能 面板、Lighthouse面板,其中Lighthouse可以生成性能报告。
检测性能之前,一般为了避免浏览器插件的干扰,会选择在无痕模式进行。
F12打开"开发工具",选择Lighthouse,点击"分析网页加载情况"按钮,即可进行性能分析,得到性能报告。我检测的是页面首次打开的性能,所以选择了"停用缓存"。性能报告包含总评分、关键指标、优化建议等。


因为选择了"开发者工具节流(高级)",所以生成的报告后面有一个"View Trace"按钮,View Trace会将刚才的测试数据放到"性能"面板里,用"性能"面板里的工具进一步分析性能问题


|-------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| 关键指标 | 含义 |
| FCP(First Contentful Paint) | 从 用户++首次++ 导航到网页到屏幕首次出现图像或文本的时间
*这是桌面设备的得分区间 |
| LCP(Largest Contentful Paint) | 从 用户++首次++ 导航到网页到屏幕出现视口内最大图片、文本块或视频的时间
*实际测试时,超过1.3s就会标红 |
| TBT(Total Blocking Time) | 在FCP之后,主线程被长任务阻塞到无法响应用户输入的总时间
*长任务:当主线程上存在运行超过50ms的长任务时,主线程会被视为"阻塞" |
| CLS(Cumulative Layout Shift) | 在网页整个生命周期内,页面发生最大布局偏移的分数。
|
2. 优化方案
2.1. 项目体积优化
在不影响功能前提下,体积越小,请求响应的时间会越短,从而减小FCP、LCP指标的时间。
可以使用rollup-plugin-visualizer插件分析打包体积,引入插件后要增加一点代码:
javascript
// vite.config.ts
import { visualizer } from 'rollup-plugin-visualizer';
export default defineConfig({
plugins: [
visualizer({
open: true, // 打包完成后自动打开报告
filename: 'stats.html', // 报告生成文件路径
template: 'treemap',
sourcemap: true, // 生成 sourcemap
}),
]
})
如果想分析打包后的结构 ,请改为 sourcemap: false。如果想看打包后的体积 ,请改为 sourcemap: true,参考链接
2.1.1. 静态资源优化
2.1.1.1 png图片优化
将png格式且大于50KB的图片转换成webp格式,保证清晰度的同时减少图片大小。
各大浏览器对Webp的支持程度:

清晰度对比:
(补图)
大小对比:

如果不能用webp,还可以用TinyPNG -- 智能压缩您的WebP、JPEG和PNG图片压缩png大小。
2.1.1.2. gif图片优化
gif格式转成MPEG-4格式。对比:

2.1.2. 开启minify压缩
在vite.config.ts里开启minify: 'terser'。
2.1.3. 引用三方库优化
2.1.3.1. antd引用优化
把所有antd/lib引用统一改为 antd/es。因为:
- /es是基于ESM模块格式,支持按需引入。
- /lib是为了兼容老项目和 nodejs 项目。
2.1.3.2. 删除重复依赖
通过`npm ls abc`分析项目中三方依赖abc是否存在版本冗余,从而决定是否要统一依赖版本。
2.1.3.3. 维护devDepencies
新增依赖时要考虑依赖用于生产环境还是开发环境,用在开发环境的依赖尽量不要放到depencies里,增加生产打包的依赖体积。
2.2. 请求响应优化
在项目体积不变的前提下,请求响应的速度越快,FCP、LCP指标的时间越短。
2.2.1. gzip/br压缩
压缩在接口响应阶段生效,网络中间层(如网关)对js/css资源 、响应体为JSON类型的响应进行压缩,降低传输数据的大小,从而提高响应速度。
比如阿里云支持Gzip压缩、Brotli压缩,通过一键配置就能降低传输数据的大小。
*注意:gzip、br不会压缩二进制类型的响应。
2.2.2. 预连接/预解析
通过提前解析DNS或建立连接,从而减少连接时间。
|------------------|--------------------------------------------------------------------------------------------------------------|
| 预解析 dns-prefetch | 只做一次DNS解析,并将解析后的IP缓存到浏览器或者OS里。 |
| 预连接 preconnect | 提前DNS解析、建立TCP连接。如果是HTTPS,还会做TLS/SSL握手。在真正请求资源时,可以直接发送HTTP/HTTPS请求。 注意:预连接会占用带宽,如果预连接后10s内不请求的话,浏览器会关闭连接。 |
参考:https://web.dev/articles/efficiently-load-third-party-javascript
2.2.3. 分包调整
在vite.config.js里,通过manualChunks属性自定义创建共享包块(chunk)。合适的分包能降低首屏资源的加载体积,从而提高性能指标。
2.3. 代码层面
代码层面通常要具体页面具体分析了,建议结合"性能"面板里的工具分析。
比如,首页图片比较多,可以考虑采用LazyLoad,避免将图片一次性加载完,降低LCP时间。
3. 总结
3.1. 总结上述用到的优化方法
- 优化图片体积
- 尽可能压缩代码
- 删除重复依赖
- 对重要资源做预连接
- 调整manualChuncks
- 使用LazyLoad、定时器做延迟加载,提高LCP
- 减少页面发生偏移的情况
3.2. 代码建议
-
优先使用Fragment组件减少DOM深度,避免DOM元素数量过大。复杂的布局可能会影响用户交互体验,Lighthouse 会对超过800个DOM节点的网页发出警告。
-
简化CSS选择器有助于加快网页的CSS计算速度。参考
css
<!-- 浏览器需要一点时间来确认"一个类为title的元素,它父元素的类是box的最后一个元素" -->
.box:last-child .title {
/* styles */
}
<!-- 如果可以,定义更具体的类会更好 -->
.final-box-title {
/* styles */
}
- 在滚动、拖拽、resize等短时间进行大量操作DOM的场景下,避免卡顿的方式有四种:
a. 使用防抖节流降低函数触发频率
b. 将读操作和写操作分开处理,在大多数情况下,应该是先读后写:
javascript
// 例1,先写后读(不推荐)
function logBoxHeight () {
box.classList.add('super-big'); // 先添加新的类
// 因为添加新的类后直接读取offsetHeight,所以浏览器会在当前帧立刻重新计算样式(强制同步布局)。
console.log(box.offsetHeight);
}
// 例2,如果新的类不影响offsetHeight的值,建议先读后写
function logBoxHeight () {
// 浏览器会拿上一帧的布局值
console.log(box.offsetHeight); // 先读取offsetHeight
box.classList.add('super-big'); // 后添加新的类
}
c. 基于b方法,使用requestAnimationFrame封装函数,要求浏览器在下次重绘前调用函数。
d. 引入三方库FastDOM解决意外触发"强制同步布局"的问题。
常见引发重排重绘的属性和方法:offsetLeft、clientLeft、getBoundingClientRect等,详细请看https://gist.github.com/paulirish/5d52fb081b3570c81e3a
- 引入依赖包尽量少用`import * from xxx`
4. 附录
4.1. png转webp方式
使用 Google开源的工具Squoosh,gif转mp4:使用Online GIF to MP4 Video converter。
Squoosh不支持批量处理。AnyWebp可以批量处理图片,缺点是不可以自定义输出质量。
如果想批量处理png转webp,并且要自定义输出图片质量,可以采用本地转换的方式:
先安装cwebp库,本地配置系统环境变量。先测试单图转换:`cwebp -q 100 image.png -o image.webp`,如果没问题可以新建一个bat文件做批量转换:
bash
# 不一定要用这个代码,根据自己想要的交互让AI生成也很不错的!
# 新建一个convert.bat文件,复制以下内容。
# 通过命令调用:./convert.bat [Image Folder Path]
# 该bat支持对文件夹内的所有png格式转成webp
@echo off
echo Starting PNG to WebP conversion...
REM Check if a folder path is provided
if "%~1"=="" (
echo Usage: convert.bat [Image Folder Path]
pause
exit /b
)
set "inputDir=%~1"
REM Check if the specified folder exists
if not exist "%inputDir%" (
echo Error: Folder "%inputDir%" does not exist.
pause
exit /b
)
REM Iterate through all .png files in the specified folder
for %%i in ("%inputDir%\*.png") do (
echo Converting %%i ...
cwebp -q 100 "%%i" -o "%%~dpi%%~ni.webp"
if errorlevel 1 (
echo Error: Failed to convert %%i.
) else (
echo Success: %%i has been converted to %%~dpi%%~ni.webp
)
)
echo All conversions completed.
Pause
4.2 获取中文版的lighthouse性能报告
如果devtools设置的是英文或者短暂设置成中文,通过devtools的lighthouse生成的报告可能不是中文,不方便解决性能问题。所以可以通过还有第二种方法生成中文报告。

4.3 参考链接
https://web.dev/learn/performance/welcome
https://developer.chrome.com/docs/performance?hl=zh-cn
https://developer.chrome.com/docs/lighthouse/performance/mainthread-work-breakdown?utm_source=lighthouse&utm_medium=node&hl=zh-cn
https://developer.chrome.com/docs/devtools/lighthouse?hl=zh-cn#main
https://github.com/GoogleChrome/lighthouse/blob/main/docs/throttling.md
https://ethcar.github.io/lighthouse/docs/throttling.html
https://developer.chrome.com/docs/devtools/performance/reference