前置储备知识点:(用户输入URL后发生什么)
- 浏览器对输入URL的域名进行DNS解析获得IP地址
- 基于IP地址和目标服务器建立连接
- 向服务器发送http请求
- 服务器处理请求返回http响应
- 浏览器解析、渲染页面
前端优化的痛点
-
目标不明确: 只会照本宣科,把别人的优化手段生搬硬套到自己的项目;
-
缺乏量化指标: 无法评估优化效果,拿不出客观、可量化的指标证明优化效果;
-
没有实质性的改善用户体验: 只优化了测试环境数据,没有真正的改善用户的主观体验;
-
没有长效化机制: 无法保证优化效果长期稳定、不出现衰退;
-
不关注开发体验: 没有认识到开发体验和用户体验的正相关性;
优化种类
- 网络优化(加载时所消耗的网络资源优化)
- 代码优化(资源加载后,脚本执行的速度)
- 框架优化(选择性能较好的框架)
webpack-bundle-analyzer插件
安装此插件,使用npm run build --report 构建完成后/dist目录内新增report.html文件
检测方面
- 显示包中所有的模块
- 显示模块size以及gzip压缩后的size
优化手段
- tree shaking(摇树):清除项目中无用代码
- split chunks(分包):入口依赖文件打包进main.js,比较大的第三方包(echarts)单独打包成一个个独立的bundle
Network面板
检测方面
可以查看网站所有资源的请求情况,包括加载时间、尺寸大小、优先级设计、HTTP缓存触发情况等信息
分析优化问题
- 压缩资源尺寸过大问题
- 合理配置缓存策略,避免导致请求加载时间过长问题
优化手段
- 减少HTTP请求
- 合并CSS
- 封装 组件,合并打包,
- 减少资源体积
- 提取第三方JS库
- 图片压缩、gzip压缩
- 缓存header(静态资源文件[强缓存],html文件[协商缓存])
- 移除console/注释冗余代码
- 使用HTTP2请求
LightHouse
检测方面
- FCP(首次内容绘制时间)/LCP(页面最大内容绘制时间)时间
- 请求并发情况,是否并发频繁
Web标准APIs
代码执行速度优化
减小文件体积/网络请求
具体实现
性能出现的原因
加载XX页面时,测试发现项目加载时会出现卡顿,
问题复现
通过前端埋点SDK、performance或者第三方监测工具,发现FCP、TTI等性能指标过长
性能指标有哪些
-
load(Onload Event),它代表页面中依赖的所有资源加载完的事件。
-
DCL(DOMContentLoaded),DOM解析完毕。
-
FP(First Paint),表示渲染出第一个像素点。FP一般在HTML解析完成或者解析一部分时候触发。
-
FCP(First Contentful Paint),表示渲染出第一个内容,这里的“内容”可以是文本、图片、canvas。【理想时间控制在1.8S内】
-
FMP(First Meaningful Paint),首次渲染有意义的内容的时间,“有意义”没有一个标准的定义,FMP的计算方法也很复杂(建议不使用,或者结合产品经理讨论使用)。
-
LCP(largest contentful Paint),最大内容渲染时间。【理想时间控制在2.5S内】
解决问题
加载层面
- 构建策略:减小文件体积
- 代码分割:SPlit chunk
- Tree Shaking
- 按需加载
- 压缩资源
- 图像处理
- 动态垫片
- 网络策略:CDN
- 缓存策略:强缓存、协商缓存
渲染层面
-
CSS策略:
- 避免出现多层的
嵌套规则 - 避免为
ID选择器添加多余选择器 - 避免使用
通配选择器,只对目标节点声明规则 - 避免重复匹配重复定义,关注
可继承属性(这点不强要求)
- 避免出现多层的
-
DOM策略:(回流重绘)
- 缓存
DOM计算属性 - 避免过多
DOM操作 - 使用
DOMFragment缓存批量化DOM操作 - 使用
display控制DOM显隐,将DOM离线化 - 在
异步任务中修改DOM时把其包装成微任务
- 缓存
-
阻塞策略:
- 脚本与
DOM/其它脚本的依赖关系很强:对<script>设置defer - 脚本与
DOM/其它脚本的依赖关系不强:对<script>设置async
- 脚本与
-
代码实践策略:
- 防抖、节流
- 懒加载
- 绘图时可开启GPU加速
- 时间分片、
Web Worker处理大、长逻辑