前端性能优化
性能指标方案
rail性能模型,Web Vitals
性能测试工具
1.Lighthouse的基本使用
在谷歌浏览器的开发者工具中
2.WebPageTest:[https://www.webpagetest.org/]
只能够测试已经发布的网址
3.Chrome DevTools测试性能、
网络请求阻止,开发者工具网络中ctrl+shift+p开启面板,然后输入block,添加不让请求的文件名
ctrl+shift+p开启面板,然后输入coverage来看未使用的内容
memory面板看哪里有内存泄漏
选择第二个时间线
performance 性能分析
fps 显示每秒帧数(FPS)指示器
performance monitor性能监视器-实时的性能分析
具体性能优化方案
1.DNS解析
(1)减少DNS查找 将这些资源划分为至少两个但不超过四个域名。这将在减少DNS查找和允许高度并行下载之间取得良好的初衷
(2)dns-prefetch是在尝试请求之前解析域名<link rel="dns-prefetch" href="https://fonts.googleapis.com"/>"
仅对跨域上的DNS有效
(3)延长DNS缓存时间,使用CDN加速域名
清楚浏览器和系统的DNS缓存
2.HTTP请求
(1)HTTP2可以多工通信,客户端发送A/B两请求,服务器端响应A请求耗时,可以先发送A请求部分数据,接着发送B请求响应,发完B接着发A
(2)看文本是否压缩传输
客户端压缩文本
Node中解压请求体中的数据
(3)强制缓存和协商缓存
区别在于判断缓存命中时,浏览器是否需要向服务器端进行询问以数据是否更新
服务器端强制缓存Expires
const data = fs.readFileSync('./img/01.jpg')
res.writeHead(200, {
Expires: new Date('2021-4-30 12:19:57').toUTCString()
})
res.end(data)
Cache-Control做强制缓存
res.writeHead(200, {
'Cache-Control': 'max-age=5' // 滑动时间,单位是秒
})
协商缓存
Cache-Control和 last-modified
const { mtime } = fs.statSync('./img/03.jpg')
const ifModifiedSince = req.headers['if-modified-since']
if (ifModifiedSince === mtime.toUTCString()) {
// 缓存生效
res.statusCode = 304
res.end()
return
}
const data = fs.readFileSync('./img/03.jpg')
res.setHeader('last-modified', mtime.toUTCString())
res.setHeader('Cache-Control', 'no-cache')
res.end(data)
ETag协商缓存,安装etag包
const data = fs.readFileSync('./img/04.jpg')
const etagContent = etag(data)
const ifNoneMatch = req.headers['if-none-match']
if (ifNoneMatch === etagContent) {
res.statusCode = 304
res.end()
return
}
res.setHeader('etag', etagContent)
res.setHeader('Cache-Control', 'no-cache')
res.end(data)
3.CDN缓存用于静态资源
CDN优化设计成与主站域名不同,原因是一避免对静态资源的请求携带不必要的Cookie信息,第二点是考虑浏览器对同一域名下并发请求的限制。
4.同构渲染
(1)通过服务器端渲染首屏,解决SPA应用首屏渲染慢以及不利于SEO问题
(2)通过客户端渲染接管页面内容交互得到更好的用户体验。
简易同构渲染代码如下所示
创建 React 组件:
// App.js
import React from 'react';
const App = ({ data }) => (
<div>
<h1>Hello, {data}</h1>
<button onClick={() => alert('Clicked!')}>Click me</button>
</div>
);
export default App;
服务器端渲染:
// server.js
import express from 'express';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import App from './App';
const app = express();
app.get('/', (req, res) => {
// 模拟从数据库获取数据
const data = 'World';
// 服务器端渲染 React 组件
const html = ReactDOMServer.renderToString(<App data={data} />);
// 将渲染后的 HTML 发送给客户端
res.send(`
<html>
<head>
<title>Isomorphic Rendering Example</title>
</head>
<body>
<div id="app">${html}</div>
<script src="/client.js"></script>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
客户端渲染:
// client.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// 从服务器端注入的数据
const initialData = window.__INITIAL_DATA__;
// 在客户端渲染 React 组件
ReactDOM.hydrate(<App data={initialData} />, document.getElementById('app'));
渲染优化
1.优化DOM 去除Html文件空格/注释/换行等缩小文件的尺寸 使用gzip压缩 使用缓存等
2.优化CSSOM css会阻塞网页的加载
让非关键CSS不阻塞渲染,在link引入css时,添加media属性,让media属性的具体值来决定请求css资源时机
避免在css中使用@import css内联style放到html中
3.js执行优化
js放到body最后
添加defer属性 脚本不会阻塞页面,会等到DOM解析完毕,但是会在DOMContentLoaded事件之前执行 有顺序的加载
async与defer不同的是谁先加载完谁先执行
利用空闲时间预加载指定的资源<link rel="preload" href="index.js">
预加载将来可能要用到的资源,非当前页面【rel="prefetch"】
js动画使用requestAnimationFrame而不用setInterval,能用css做动画用css做动画,requestAnimationFrame是在渲染一帧之后执行
function run () {
if (box.offsetLeft >= 200) {
box.style.left = '200px'
return
}
box.style.left = `${box.offsetLeft + 1}px`
window.requestAnimationFrame(run)
}
window.requestAnimationFrame(run)
恰当使用web Worker
节流(在规定时间内响应第一次触发的事件),防抖(在最后一次事件发生后,经过规定时间触发事件)
css引擎在查找样式表时,对于每条规则的匹配都是从右向左的 BEM样式编码规范
减少页面布局和重绘的发生 查看更多工具rendering
图片延迟加载 对于不在视窗中的图片将src 属性变为data-src属性,当图片在视窗中之后将src属性赋值为data-src属性