浏览器上输入一个url之后的全过程
-
输入url后, 首先会将url的域名通过
DNS解析得到一个服务器的ip地址, 之后该DNS解析的结果将被缓存起来, 下次访问相同域名时, 可以直接从缓存中获取, 减少解析时间 -
拿到
ip之后, 浏览器和服务器通过TCP三次握手建立通信, 首先客户端发送SYN到服务器, 然后服务器发送SYN+ACK到浏览器, 之后浏览器再发送ACK到服务器 -
如果是
http链接,TCP三次握手之后就能开始通信, 但是如果是https链接, 就需要再加一次握手, 即TLS协商. 主要过程: 浏览器发送clientHello到服务器, 服务器返回serviceHello & Certificate到浏览器, 浏览器发送clientKey到服务器, 服务器验证没问题后发送finished到浏览器, 浏览器发送finished到服务器, 链接创建完成 -
链接创建之后, 服务器开始向浏览器发送相应数据, 这里涉及一个
TCP慢开始, 即第一个响应包的大小不会超过14KB. 慢开始是一种均衡网络链接速度的一种算法, 慢开始逐渐增加发送数据的数据量直到网络最大带宽 -
浏览器关键路径渲染, 浏览器解析数据, 浏览器会先解析拿到的数据, 解析其中的
html, css, js并将其渲染到页面上-
处理HTML标记并构建DOM树
- 字节 -> 字符 -> 令牌 -> 节点 -> DOM树 这个过程是增量的
incremental - 当解析器碰到非阻塞资源时, 浏览器会请求资源并继续解析; 当遇到图片,CSS文件等资源文件时, 解析不会中断, 但是当碰到JS文件特别是没有
async, defer属性的文件资源将会阻塞渲染并停止DOM树的解析 - 预加载扫描器: 在构建DOM树时, 这个过程会占据主线程. 这个时候预加载扫描器就会在后台解析可用的内容并请求高优先级资源. 可以减少因为JS等资源加载造成的阻塞.
- CSS文件加载不会影响DOM树的构建, 但是会阻塞JS文件的加载, 因为JS文件可能会查询CSS属性
- 字节 -> 字符 -> 令牌 -> 节点 -> DOM树 这个过程是增量的
-
构建CSSOM(recalculate style)
- 字节 -> 字符 -> 令牌 -> 节点 -> CSSOM树 这个过程不能增量进行, css加载会阻塞浏览器渲染
- 从最通用的规则开始, 并通过应用更具体的规则递归的计算样式
- 构建CSSOM的时间很快, 在开发者工具的“重新计算样式”这个指标可以看出, 解析CSS, 构建CSSOM和递归计算样式所需要的总时间, 一般都不会超过一次DNS解析的时间
- 所以需要先观察css解析是否会消耗很长时间, 然后再决定是否优化
- 由于JS文件可能会操作CSS样式, 从而需要先进行CSSDOM的渲染,而阻塞DOM树的渲染
-
根据CSSOM和DOM构建RenderDOM,
- 从DOM树的根节点开始遍历每个可见元素,每个可见节点上都有对应的CSSOM规则.
- Render树保存了所有具有内容和计算样式的可见节点.
- 将所有关联像是匹配到DOM树的可见节点上, 并根据CSS级联确定每个节点的计算样式
-
布局(layout)
- 根据渲染树来进行布局, 从渲染树的根节点开始, 计算每个节点实际宽度, 高度, 位置信息
- 第一次确定节点大小和位置称为布局, 后续对节点大小和位置的调整称为回流
- 例如, html上有一个没有设置大小的图片, 在第一次布局的时候只会给图片提供一个占位, 等图片资源加载完毕之后就可以拿到图片的大小, 会进行回流操作
-
绘制(paint)
- 最后一步是将布局绘制到屏幕上, 第一次进行绘制的节点被称为
first meaningful paint - 为了保证平滑的滚动和动画效果, 主线程的所有操作包括回流, 计算样式和绘制, 需要在16.67ms内完成
- 绘制可以将布局树分解成多个层, 将内容提升到GPU上的层, 可以提高绘制和重新绘制的性能
- 有一些特定的属性和元素可以实例化一个层, 比如
video, canvas, 任何CSS属性为opacity, willchange和3D转换 - 这些节点和他们的子节点会绘制在一个层上
- 层确实可以提高性能, 但是它以内存为代价, 因此不能作为web性能优化而过度使用
- 最后一步是将布局绘制到屏幕上, 第一次进行绘制的节点被称为
-
合成(composite layer)
- 当文档的各个部分以不同的层进行绘制, 相互重叠时, 必须要进行合成. 以确保它们以正确的顺序显示在屏幕上
-
交互
Time To Interactive是测量从第一个请求导致的DNS查找和SSL连接到页面可交互时所用的时间- 如果存在
defer类型的js文件, 则会在页面onLoad之后触发执行, 占用主线程, 从而无法进行滚动, 触摸等其他用户交互效果
-
-
js的加载方式
-
async和defer的区别async是文件加载完成, 渲染引擎就会中断渲染, 执行这个脚本后再继续渲染, 不会阻塞DOM构建, 也不会影响CSSOM创建defer是文件加载完成后, 等到渲染引擎渲染完成(DOM结构完全生成, 其他文件渲染完成)之后才会执行渲染, 并且多个defer文件之间的执行是顺序的defer的js文件会在DOMContentLoaded之前按照顺序执行
-