性能优化原理
加载阶段
加载阶段可以划分为URL请求和渲染两个阶段
URL请求阶段
URL请求阶段主要包含:缓存、DNS检查和发送HTTP请求,这个阶段通常是服务器的响应时间占用大部分的时间。对于静态资源,服务器的响应时间一般不会成为瓶颈;而对于服务端渲染则需要进行缓存等优化处理
常用的优化手段如下:
- 减少重定向;
- 服务器升级带宽;
- 升级服务器配置;
- 数据库优化(对于服务器渲染的页面);
- 缓存动态网页(对于服务器渲染的页面);
- 善用缓存;
- 静态资源的使用;
- 使用httpDNS;
- 更换高防服务器(有可能是服务器被攻击导致缓慢);
渲染阶段
渲染阶段主要包括:解析HTML构建DOM、样式计算、布局、分层、绘制、栅格化和合成这几个步骤。这其中耗时较长,最容易造成瓶颈的是构建DOM树和计算样式这两个步骤。
常用的优化手段如下:
- 资源量尽可能少(压缩、雪碧图、按需加载);
- 请求次数尽可能少(打包);
- 让无依赖关系的资源尽可能早加载而不是等待排队(域名打散、分包,即并行);
- 请求链路尽可能少(CDN);
- 尽可能早解析DNS(DNS预解析);
- 使用强缓存,文件名加hash后缀,这样只要文件内容不变,就会读缓存内容;
- 组件懒加载,路由懒加载,其实路由懒加载本质也是组件懒加载;
- 其他资源懒加载,避免由于模块引用关系不当,导致首屏页面加载了首屏用不到的CSS、字体图标、图片等资源
- 异步加载js(async、defer、放到body底部、动态创建script标签);
- 不使用CSS @import(CSS的@import会造成额外的请求);
- 避免空的src和href (留意具有这两个属性的标签如link,script,img,iframe等);
运行阶段
如果JavaScript做了修改DOM元素的几何属性(位置、尺寸)等操作,将会重新计算style,并且需要更新布局树,然后执行后面的渲染操作。这个过程叫“重排”。
如果JavaScript修改了DOM的非几何属性,如修改了元素的背景颜色,不需要更新布局树和重新构建分层树,只需要“重新绘制”。
除了首次加载,还有一些其他的操作会引起重排
-
DOM元素移动、增加、删除和内容改变会触发回流。
-
当DOM元素的几何属性(
width
/height
/padding
/margin
/border
)发生变化就会触发回流。 -
读写元素的
offset
/scroll
/client
等属性会触发回流。 -
调用
window.getComputedStyle
会触发回流。
因此,常用的优化手段是尽量避免DOM的重排和重新绘制:
- 避免元素影响到所在文档流(用绝对定位,CSS的transform属性实现动画不会导致重排和重绘);
- 读写分离()