面试或笔试的时候经常会被问到“:
在浏览器中输入URL到整个页面显示在用户面前时这个过程中到底发生了什么?”、“从浏览器中输入URL到页面加载的发生了什么?“。当你认真回答完这个问题后,面试官可能会再问“在代码层面如何在浏览器绘制前减少重绘重排(回流)?”
总的来说,从地址栏输入url按下回车到页面完全展示
,大致经历以下几个步骤:
在谈web性能优化前,来看一张图“延迟与用户反应”。
不难看出,页面响应超过1-10s用户可能就关闭放弃页面。为了更将信息快速响应给用户提供友好交互,留住用户,需要将信息再尽短的时间内反馈给用户。
如何尽快的加载资源?答案就是能不从网络中加载的资源就不从网络中加载,当我们合理使用缓存,将资源放在浏览器端,这是最快的方式。如果资源必须从网络中加载,则要考虑缩短连接时间,即DNS优化部分;减少响应内容大小,即对内容进行压缩。另一方面,如果加载的资源数比较少的话,也可以快速的响应用户。当资源到达浏览器之后,浏览器开始进行解析渲染,浏览器中最耗时的部分就是reflow。所以接下来从以上几个阶段开始。
DNS解析过程:
DNS查询顺序:浏览器缓存→系统缓存→路由器缓存→ISP DNS 缓存→递归搜索
了解DNS解析过程,能为我们带来什么呢?可以得出,要更快解析到服务器IP,一要不减少解析步骤(DNS缓存),二要不就是提前解析(DNS预解析)
只要有DNS解析的地方就有dns缓存,默认浏览器会缓存访问过域名的ip地址
服务器在完成 HTTP 请求之后不断开 TCP 连接而是挂起,后续有 HTTP 请求可以直接在这个 TCP 连接上发送;缺点是保持长连接会消耗服务端的资源。
HTTP/2 多路复用的特性允许多个 HTTP 请求在同一个 TCP 连接上发送,可以节省多次建立 TCP 连接的时间。
http优化主要减少http请求次数、单次请求所花的时间
减少文件体积是减少单次请求所花时间的主要手段。
优化方法主要有:
构建阶段压缩:通过删除多余空格和空行以及变量名替换(用字符较少的变量名替换字符较多的变量名)减少文件的字符数量。
HTTP 压缩(内容编码):对 HTTP 所传的内容重新编码,缩小文件的体积,例如 Gzip 压缩。
将文件按 url 路径(或者采用更小粒度)进行拆分,优先加载关键渲染路径所依赖的文件,其他文件在需要的时候再异步请求,以 Vue 项目为例
// 异步组件,会按需加载
const SearchToast = () => ({
component: import('component/search-toast.vue'),
});
缓存可以减少网络 IO 消耗,提高页面访问速度
1)对于动画效果的实现,避免使用 setTimeout 或 setInterval,使用 requestAnimationFrame
2)如果不需要访问 DOM,可以将长时间运行的 Javascript 工作从主线程移动 worker 线程
3)如果必须在主线程上执行大型任务,可以将大型任务分割为多个微任务,每个微任务所占时间不超过几毫秒
降低选择器的复杂性,使用以类为中心的方法,比如 BEM:
// 渲染性能比较好的方式
.final-box-title {
/* styles */
}
// 渲染性能比较差的方式
.box:nth-last-child(-n+1) .title p {
/* styles */
}
布局是浏览器计算各元素的几何信息的过程,包括元素的大小和在页面中的位置。
1)尽可能避免布局操作
几何属性(高度、宽度、位置等)的更改都会引发布局计算,而布局几乎总是作用到整个文档,所以会耗费大量性能。
2)使用 flexbox 布局模型
flexbox 布局模型的性能更好。
绘制是浏览器填充像素的过程。绘制通常是渲染过程中性能开销最大的部分,应该尽可能避免绘制。
将元素提升为合成层:
.moving-element {
will-change: transform;
translate3D(120, 0, 0);
}
// 不支持 will-change 的浏览器
.moving-element {
transform: translateZ(0);
}
will-change应用:滚动视差效果的实现及优化方案
提升为合成层的元素,transform 和 opacity 的改变不会引发绘制,只会引发合成。
但也要注意不要创建太多层,因为每层都需要内存和管理开销。
减少绘制的区域 减少绘制区域往往是编排您的动画和变换,使其不过多重叠,或设法避免对页面的某些部分设置动画。
降低绘制的复杂性 在谈到绘制时,一些绘制比其他绘制的开销更大。
合成是将页面已绘制的部分放在一起在屏幕上显示的过程。
页面中的合成层数量不宜太多,如果没有必要,还是不要讲元素提升为合成层。
影响页面的性能因素:
1)需要管理的合成器层数量
2)动画属性
坚持使用 transform 和 opacity 属性更改来实现动画
使用 transform 和 opacity 时要注意的是,这些属性所在的元素应处于其自身的合成器层(will-change 提升)。
管理层并避免层数激增 如无必要,请勿提升元素
硬件加速transform、opacity测试例子