1. 性能指标和优化目标
- 理解加载瀑布图
- 基于HAR存储与重建性能信息
- 速度指数(Speed Index)
- 重要测量指标
- 瀑布图
蓝色线为dom加载完成时间,红色线为页面所有声明资源加载完成时间
鼠标放在某一段上可查看详细信息
- lighthouse
关心下面两个指标即可:
- First Contentful Paint: 首次有内容的绘制时间,即页面不再白屏
- Speed Index: 4s左右为正常
- 交互流畅度
command + shift + p
60fps(帧)以上为流畅
异步请求都控制在1s内,超过1s,前端加交互,如loading
2. RAIL测量模型
- Response 响应(这里指交互,比如点击等操作)
- Animation 动画
- Idle 空闲
- Load 加载
- 响应:处理事件应在50ms内完成
- 动画:每10ms产生1帧
- 空闲:尽可能增加空闲时间
- 加载:在5s内完成内容加载并可以交互
性能测量工具:
- Chrome DevTools开发调试、性能评测
- Lighthouse 网站整体质量评估
- WebPageTest 多测试地点、全面性能报告
3. 使用WebPageTest评估Web网站性能
观察以下三部分:
- waterfall chart请求瀑布图
- First View: 首次访问
- Repeat View: 再次访问
4. 使用LightHouse分析性能
npm install -g lighthouse
lighthouse https://www.taobao.com
First Contentful Paint: 第一个有意义内容绘制
Speed Index: 速度指数,4s左右为正常
Largest Contentful Paint:可见资源里最大资源花费时间
Time to Interactive:可交互时间
截屏10张有7张是白的,说明没有做渐进式优化(说明页面不是逐步加载的,而是一下子全部加载出来)
优化建议与诊断:
过滤某些资源,使它不让加载,通过这种方式判断该资源是否是页面加载所必须的。
5. 使用Chrome DevTools分析性能
- Audit(Lighthouse)
- Throttling调整网络吞吐
- Performance 性能分析
- Network 网络加载分析
第一个为网络传输大小,第二个位实际大小,网络传输资源可以被压缩。
以下为压缩静态资源代码:
动态压缩,与nginx的Gzip不一样
查看是否有长任务:
开发时可以取消缓存(disable cache),防止修改代码不生效
在控制台按esc键,可以调出常用功能:
6. 常用的性能测量APIs
- 关键时间节点(Navigation Timing , Resource Timing)
- 网络状态(Network APIs)
- 客户端服务端协商(HTTP Client Hints) &网页显示状态(UI APIs)
// 计算一些关键的性能指标
// load事件后触发
window.addEventListener('load', (event) => {
// Time to Interactive 可交互时间
let timing = performance.getEntriesByType('navigation')[0];
console.log(timing.domInteractive);
console.log(timing.fetchStart);
let diff = timing.domInteractive - timing.fetchStart;
console.log("TTI: " + diff);
})
// 观察长任务
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry)
}
})
observer.observe({entryTypes: ['longtask']})
// 页面可见性的状态监听,用户是否正在浏览页面,切换页面就会触发
let vEvent = 'visibilitychange';
if (document.webkitHidden != undefined) {
// webkit prefix detected
vEvent = 'webkitvisibilitychange';
}
function visibilityChanged() {
if (document.hidden || document.webkitHidden) {
console.log("Web page is hidden.")
} else {
console.log("Web page is visible.")
}
}
document.addEventListener(vEvent, visibilityChanged, false);
// 判断网络状态
var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
var type = connection.effectiveType;
function updateConnectionStatus() {
console.log("Connection type changed from " + type + " to " + connection.effectiveType);
type = connection.effectiveType;
}
connection.addEventListener('change', updateConnectionStatus);