性能优化
1. 前端性能优化方法(待补充)
页面展示可以分为3个阶段,请求页面,加载和解析页面,渲染。
(主要优化方法请参考知识点链接)
1、请求数据阶段主要指标是服务器响应时间,从服务器角度优化。
2、加载和解析页面阶段,性能优化的主要思路是减少请求数量、降低资源的大小和避免阻塞。
3、渲染阶段优化思路是避免重绘和重排。
2. 白屏和首屏时间
如何计算白屏和首屏时间?onload事件发生了什么?
白屏结束时间 = FP事件触发时间
首屏结束时间 = FCP事件触发时间
FP(First Paint)表示渲染出第一个像素点的时间。FP一般在HTML解析完成或者解析一部分时候触发。
FCP(First Contentful Paint)表示渲染出第一个内容的时间,这里的“内容”可以是文本、图片、canvas。
FMP(First Meaningful Paint),首次渲染有意义的内容的时间,“有意义”没有一个标准的定义,FMP的计算方法也很复杂。
Onload Event,它代表页面中依赖的所有资源:DOM、图片、CSS、Flash等都加载完。
指标计算方法
// FP
const fp = performance.getEntries('paint').filter(entry => entry.name == 'first-paint')[0].startTime;
// FCP
const fcp = performance.getEntries('paint').filter(entry => entry.name == 'first-contentful-paint')[0].startTime;
// Onload Event
const l = performance.timing.loadEventEnd - performance.timing.navigationStart;3. 浏览器渲染过程
4. js动画为什么会有性能问题?
因为js动画修改了style会导致重排,重排触发重新计算布局树并且生成分层树,造成性能损耗。
5. setTimeout、requestAnimationFrame和requestIdleCallback的区别
通常我们可以通过定时器(setTimeout/setInterval)实现一个动画,但是定时器时间并不精确,如果时间太短,那么可能造成多余的操作,消耗CPU,如果时间长,就会导致动画不流畅。另外当画面不展示时候,定时器依然执行,导致不必要的CPU资源消耗,耗电更快。
requestAnimationFrame实现动画可以解决上面两个问题。
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
该回调函数会被传入DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻,这个时间用来进行动画参数的计算。
const element = document.getElementById('some-element-you-want-to-animate');
let start;
function step(timestamp) {
if (start === undefined){
start = timestamp;
}
const elapsed = timestamp - start;
//这里使用`Math.min()`确保元素刚好停在200px的位置。
element.style.transform = 'translateX(' + Math.min(0.1 * elapsed, 200) + 'px)';
if (elapsed < 2000) { // 在两秒后停止动画
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);由于该方法只是通知浏览器下一次绘制之前执行一次callback,因此实现动画时候需要每次重新调用。
requestAnimationFrame返回一个id,取消回调的方法是cancelAnimationFrame,请看官方示例
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
// 只有Firefox支持mozAnimationStartTime属性,其他浏览器可以使用Date.now()来替代.
var start = window.mozAnimationStartTime;
var myReq;
function step(timestamp) {
var progress = timestamp - start;
d.style.left = Math.min(progress/10, 200) + "px";
if (progress < 2000) {
myReq = requestAnimationFrame(step);
}
}
myReq = requestAnimationFrame(step);
window.cancelAnimationFrame(myReq);requestIdleCallback
接受一个回调,回调在浏览器空闲时间执行。注意如果浏览器一直渲染没有空闲,可能就一直执行不到requestIdelCallback注册的回调,因此可以设置一个超时时间,超时之后会执行注册的回调。
取消回调的方法是 cancelIdleCallback
var handle = window.requestIdleCallback(callback, {timeout: 1000});
cancelIdleCallback(handle);注意,requestIdleCallback用来执行优先级低的任务,由于其执行时机不可控,因此尽量不要执行DOM操作。
6. 什么会阻塞dom渲染
-
css解析会阻塞渲染。因为构造渲染树需要CSSOM,因此CSS解析完成是后续工作的先决条件。
-
css下载会阻塞js执行,不会阻塞html解析。
-
js下载和执行会阻塞html。
-
在执行 JavaScript 脚本之前,会先加载并解析页面中的CSS样式(包括link标签和style标签)(如果存在)。也就是说 CSS 在部分情况下也会阻塞 DOM 的生成。
7. script标签什么情况不阻塞渲染
async、defer和动态创建标签。
可以让script异步加载避免阻塞dom渲染,提升首屏渲染速度。
8. 重绘与重排
9. 用户页面打开很慢,有哪些优化方式?
下面列举常见的加载阶段性能优化方法,这些优化方法都是根据“尽可能少”、“尽可能早”的原则实现的优化手段。
1. 减少需要请求的资源尺寸:资源压缩、删除冗余代码和其他资源,或者使用尺寸更小的资源
-
代码压缩,包括js/css/html都应该压缩。
-
服务器开启gzip。
-
iconfont代替图片。
-
使用webp图片,在质量相同的情况下,WebP 格式图像的体积要比 JPEG 格式图像小 40%。
-
删除无用代码(摇树js和css、删除console.log)。
-
模块按需加载(antd、lodash、moment等常用的第三方库,不用的模块不打包进项目)
2. 减少请求数量
-
合并请求,由于每次请求时候,实际传输的内容只占整个请求过程的较少一部分时间,因此合并内容让多个请求变成一个可以节约请求中建立连接、排队等待等耗时。
-
雪碧图,图片合成,避免每个图片都要发一次请求。
-
内联较小的js css、图片(转成base64)等资源,避免再发一次请求获取资源。
3. 缓存
-
使用强缓存,文件名加hash后缀,这样只要文件内容不变,就会读缓存内容。
-
文件分包,更好地利用缓存,不常改变的资源分离出来。
-
使用cdn,注意要避免html被cdn缓存,可以在cdn服务配置不缓存html资源,也可以把html部署在自己的服务器。
4. 并行请求
-
域名打散(针对http1)。
-
使用http2。(当然http2还有二进制等好处)。
5. 按需加载
-
图片按需加载,只下载可视区附近的图片。
-
组件懒加载,路由懒加载,其实路由懒加载本质也是组件懒加载。
-
其他资源懒加载,避免由于模块引用关系不当,导致首屏页面加载了首屏用不到的CSS、字体图标、图片等资源。
6. 预加载
-
dns预解析,使用
< link rel="dns-prefetch"href="//my.domain">对域名做预解析,后续资源加载时候会跳过dns预解析的阶段,直接使用dns的结果。 -
资源预加载,首屏完成后,可以采取某种机制预加载二屏资源。
7. 注意事项
-
异步加载js(async、defer、放到body底部、动态创建script标签)。
-
不使用CSS @import,CSS的@import会造成额外的请求 用代替@import 。
-
避免空的src和href 留意具有这两个属性的标签如link,script,img,iframe等;
8. 服务端渲染和预渲染。
主流框架都支持SSR,并有开箱即用的框架,服务端渲染有优异的首屏性能,并且对SEO更友好。
预渲染目的提升首屏性能,预渲染就是在构建阶段,启用无头浏览器,加载项目的路由,并渲染出首屏页面(也可以配置其他路由),然后生成静态页面,输出到指定的目录。
prerender-spa-plugin插件启用无头浏览器,加载项目的路由,并渲染出首屏页面(也可以配置其他路由),然后生成静态页面,保存在指定的目录。
我们的静态资源服务器就可以serve预渲染的页面了。
使用这个插件相当于在构建阶段就渲染好了首屏页面,极大地提升了首屏性能。
9. css和js加载,是同步还是异步?
css加载不会阻塞html解析,但是渲染会等待css下载并解析完才能进行。
js的执行需要等待css下载完成。
js执行默认是会阻塞html解析的,给script标签加defer和async属性,或者采用动态创建script标签方式,js就不会阻塞html。