性能检测工具
webpagetest:https://www.webpagetest.org/(测试功能需要fanqiang)
lighthouse:npm全局安装,或直接使用chrome devtools的lighthouse
performance: chrome devtools的performance
浏览器的渲染:
浏览器构建Dom对象和构建cssOM对象;
浏览器构建渲染树;
布局(位置、大小);
绘制;
合图层;
浏览器的渲染流程:
1.触发view变化;
2.重新计算样式变化(dom,cssom,render树);
3.布局;
4.绘制(分层绘制,提高效率);
5.合图层;
优化:如果变化不改变布局,可以不经历布局和重绘
影响回流(再次布局)的操作:
- 添加、删除元素;
- 操作styles
- display:none;
- offsetLeft,scrollTop,clientWidth;
- 移动元素的位置;
- 修改浏览器大小,字体大小;
避免layout thrashing:
- 避免回流,比如:避免修改top,bottom位置,使用transform(触发复合图层)
- 读写分离, 比如:将读取元素位置和大小的属性offsetTop,和修改元素位置和大小属性,分离,先批量读,在批量写。
- fastdom可以帮你处理读写分离
优化前(回流):
let cards = document.getElementsByClassName('card') const update=(timestamp) => { for (let index = 0; index < cards.length; index++) { const card = array[index]; card.style.width = ((Math.sin(card.offsetTop + timestamp / 1000) + 1) * 200) + 'px' window.requestAnimationFrame(update) } } window.addEventListener('load', (event) => { update() })
优化后(读写分离,避免了回流):
let cards = document.getElementsByClassName('card') const update=(timestamp) => { for (let index = 0; index < cards.length; index++) { fastdom.measure(()=>{ //读取top const card = cards[index]; const offsetTop = card.offsetTop; fastdom.mutate(()=>{ //写 card.style.width = ((Math.sin(offsetTop + timestamp / 1000) + 1) * 200) + 'px' }) }) } window.requestAnimationFrame(update) } window.addEventListener('load', (event) => { update() })
复合线程
将页面拆分图层进行绘制再进行复合
拆分图层的规则
由浏览器决定
元素之间的相互影响,如果图层对其他图层影响比较多
只影响复合的样式
Position:transform:translate(x,y)
Scale: transform:scale(n)
Rotation: transform: rotate(n)
Opacity: opacity: 0~1
优化: 避免修改产生重绘样式,选择只复合的样式
避免重绘(加速页面呈现)
ctrl+shift+p-->show rendering-->paint flashing, 标绿发生重绘的元素
css属性:will-change
CSS 属性 will-change
为web开发者提供了一种告知浏览器该元素会有哪些变化的方法,这样浏览器可以在元素属性真正发生变化之前提前做好对应的优化准备工作。 这种优化可以将一部分复杂的计算工作提前准备好,使页面的反应更为快速灵敏。
兼容性较差。
注意:
- 不要将此属性应用到太多的元素上;
- 有节制地使用,最佳实践是当元素变化之前和之后通过脚本来切换
will-change
的值; - 不要过早应用will-change优化,能不用就不用,设计初衷是作为最后的优化手段;
- 给它足够多的工作时间,浏览器需要在发生变化前,做优化准备,使用时需要使用一些方法提前一定时间获知元素可能发生的变化,然后在加上will-change属性;
此属性的正确使用步骤是,通过脚本提前一定时间获知元素可能发生的变化,为此元素加上will-change属性,在变化结束之后,去除此元素的will-change属性。
属性的取值:
1、auto: 初始值,没有指定哪些属性会变化,浏览器自己使用常规优化。
2、scroll-position: 表示开发者希望在不久后改变滚动条的位置或者使之产生动画。
3、contents: 表示开发者希望在不久后改变元素内容中的某些东西,或者使它们产生动画。
4、<custom-ident>: 表示开发者希望在不久后改变指定的属性名或者使之产生动画。如果属性名是简写,则代表所有与之对应的简写或者全写的属性。
var el = document.getElementById('element'); // 当鼠标移动到该元素上时给该元素设置 will-change 属性 el.addEventListener('mouseenter', hintBrowser); // 当 CSS 动画结束后清除 will-change 属性 el.addEventListener('animationEnd', removeHint); function hintBrowser() { // 填写上那些你知道的,会在 CSS 动画中发生改变的 CSS 属性名们 this.style.willChange = 'transform, opacity'; } function removeHint() { this.style.willChange = 'auto'; }
高频事件处理函数防抖
如滚动,touchstart, mouseOver等等;
一帧中可能触发很多次;
顺畅的帧率:60fps
一帧时间:16ms
一帧的生命周期
input events: blocking input events: touchwheel;no-blocking input events:clickkeypress;
timers: js
begin frame:
1.window resize
2.scroll
3.mediaquery changed
4.animation events
rAF:
1.requestAnimation-Frame callBacks
2.Intersection-Observer callBacks
Layout
1.recalc style
2.update layout
3.resize-observer callbacks
paint
1.compositing update
2.paint invalidation
3.record