性能-网站和应用的支柱
- 流量
- 搜索
- 转换率
- 用户体验
现状
移动端
- 设备硬件,网速,屏幕尺寸,交互方式
- 用户更缺少耐心,>3s 加载导致 53% 的跳出率(bounce rate)
- 持续增长的移动用户和移动电商业务
性能指标和优化目标
性能优化-加载
- 瀑布图
- HAR 存储
- 速度指数(speed index)
重要测量指标
交互动作的反馈时间
- FPS (Frames Per Second)
-
RAIL 测量模型
Response 响应
- 100ms 内响应用户事件
- Animation 动画
- 动画每 16.7ms 传输新的一帧在屏幕上
- Idle 空闲
- 每一个空闲任务不超过 50ms
- 尽可能增加空闲时间
- Load 加载
- 3G 中等设备 5s 内完成内容加载并可交互
性能测量工具
Chrome DevTools 开发调试、性能评测
- Network 网络加载分析
- Performance 性能分析
- Throttling 调整网络吞吐
-
Lighthouse 网站整体质量评估
WebPageTest 多测试地点、全面性能报告
waterfall chart 请求瀑布图
- first view 首页访问
-
本地部署 webpagetest
安装 docker
- 拉取镜像 ```bash docker pull webpagetest/server
docker pull webpagetest/agent
- 运行实例
```bash
docker run -d -p 4000:80 webpagetest/server
docker run -d -p 4001:80 --network="host" -e "SERVER_URL=http://localhost:4000/work/" -e "LOCATION=Test" webpagetest/agent
配置 server
mkdir wpt-mac-server cd wpt-mac-server vim Dockerfile
FROM webpagetest/server ADD locations.ini /var/www/html/settings/
vim location.ini
[locations] 1=Test_loc [Test_loc] 1=Test label=Test Location group=Desktop [Test] browser=Chrome,Firefox label="Test Location" connectivity=LAN
打包 server
docker build -t wpt-mac-server .
配置 agent
cd ../ mkdir wpt-mac-agent cd wpt-mac-agent vim Dockerfile
FROM webpagetest/agent ADD script.sh / ENTRYPOINT /script.sh
vim script.sh
#!/bin/bash set -e if [ -z "$SERVER_URL" ]; then echo >&2 'SERVER_URL not set' exit 1 fi if [ -z "$LOCATION" ]; then echo >&2 'LOCATION not set' exit 1 fi EXTRA_ARGS="" if [ -n "$NAME" ]; then EXTRA_ARGS="$EXTRA_ARGS --name $NAME" fi python /wptagent/wptagent.py --server $SERVER_URL --location $LOCATION $EXTRA_ARGS --xvfb --dockerized -vvvvv --shaper none
chmod u+x script.sh
打包 agent
docker build -t wpt-mac-agent .
用新镜像运行实例 (注意先停掉之前运行的containers) ```bash docker ps
docker stop serverID agentID
docker run -d -p 4000:80 wpt-mac-server
docker run -d -p 4001:80 —network=”host” -e “SERVER_URL=http://localhost:4000/work/“ -e “LOCATION=Test” wpt-mac-agent
<a name="clGvf"></a>
## 常用的性能测量 APIs
<a name="yHOJS"></a>
### 关键性能指标计算
DNS 解析耗时: domainLookupEnd - domainLookupStart TCP 连接耗时: connectEnd - connectStart SSL 安全连接耗时: connectEnd - secureConnectionStart 网络请求耗时 (TTFB): responseStart - requestStart 数据传输耗时: responseEnd - responseStart DOM 解析耗时: domInteractive - responseEnd 资源加载耗时: loadEventStart - domContentLoadedEventEnd First Byte时间: responseStart - domainLookupStart 白屏时间: responseEnd - fetchStart 首次可交互时间: domInteractive - fetchStart DOM Ready 时间: domContentLoadEventEnd - fetchStart 页面完全加载时间: loadEventStart - fetchStart http 头部大小: transferSize - encodedBodySize 重定向次数:performance.navigation.redirectCount 重定向耗时: redirectEnd - redirectStart
```javascript
// 计算一些关键的性能指标
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);
})
PerformanceObserver
// 观察长任务
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry)
}
})
observer.observe({entryTypes: ['longtask']})
visibilitychange
// 页面可见性的状态监听
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);
navigator.connection
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);