渊虹小站

浏览器内部:网页渲染流程

渲染进程中的线程

渲染进程的主要任务,是将HTML、CSS和JavaScript变成用户可以与之交互的网页

  • GUI渲染线程 — 主线程
  • compositor线程
  • raster线程
  • JavaScript引擎线程
  • 事件触发线程
  • 定时器触发线程
  • 异步http请求线程

网页渲染流程

  • HTML解析

    • 接受到HTML后,主线程会将HTML解析为DOM
    • 在解析HTML的过程中,如果遇到 <script>标签,HTML解析需要停止,进行JavaScript的加载、解析与执行。原因是JavaScript可能会使用document.write等方法改变DOM结构
  • 样式解析。主线程将CSS解析为样式规则。
  • 样式封装。当DOM和CSS解析全部完成之后,主线程会根据CSS选择器和样式规则,计算每个元素的样式,这个阶段的结果是渲染树。渲染树包含对应于各个元素的带有各种样式视觉信息(包括颜色、尺寸等)的矩形。
  • 布局。渲染树构建完毕后,开始进行布局。布局阶段,主线程会计算每个元素在页面应该处于位置的坐标,最终产出布局树。
  • 绘制顺序。有了布局树后,主线程会遍历布局树,来决定每个元素的绘制顺序。绘制顺序包括:每个元素的绘制顺序,比如设置了z-index的元素,绘制顺序会有所改变;已经元素先背景、再文字的绘制顺序等。
  • 图层树。主线程会将页面分为各个图层,不同的元素有可能会被分到不同的图层上,为了决定哪个元素应该位于哪个图层上,主线程会遍历布局树,产出图层树。图层树可以通过chrome开发者工具-More tool-Layer进行查看。
  • 栅格化。图层树和绘制顺序创建完毕后,主线程会把这些信息提交给 compositor线程,compositor线程会把较大的图层分为小块,分别交给 raster线程 进行栅格化。
  • 最终展示。每个小块被栅格化完成后,compositor线程会收集这些完成栅格化的小块,形成 compositor帧。compositor帧由渲染进程通过IPC交给browser进程,进而交给GPU,最终展示在屏幕上。

DOM解析的一些其他问题

预解析

预解析,不同于主线程的正式HTML解析,它会专门去找HTML中嵌入的外部资源,包括CSS、图片、JavaScript等,并进行提前加载,以节省时间。

找到这些内容后,渲染进程会将这些需要加载的内容交给broswer进程中的network线程,让它去发起网络请求,加载这些资源,而渲染进程中的主线程则会同步进行HTML解析

预防DOM解析阻塞

有一些方法可以避免JavaScript的加载和执行阻塞DOM解析,比如

  • 如果脚本不影响DOM结构,则可以给<script>标签加上asyncdefer标签,使JavaScript加载变成异步

    • 加了async,则加载 JavaScript 和 DOM解析会同步进行 (JavaScript的加载时由browser进程中network线程进行,不影响DOM解析)。JavaScript加载完毕后,停止DOM解析,进行JavaScript的解析和执行,JavaScript解析和执行完毕后继续进行DOM 解析
    • 加了defer,则加载JavaScript和DOM解析会同步进行,JavaScript加载完毕后会进行等待,DOM全部解析完毕后,才会解析和执行这些JavaScript。浏览器会保证所有加了defer属性的脚本,会按照它们的排列顺序从上往下依次执行
  • 如果资源是一定会用到的,可以加上rel=preload属性,则可以使页面尽快下载,而不是等到HTML解析到了才开始下载

接下来

  • 在这里描述的只是网页渲染的一个大纲,后续有深入了解再进行补充,后面参考资料中也有更多相关详情
  • 由网页渲染流程,可以看到一系列网页优化的方法。从加载资源,到构建DOM、构建CSSOM树等,在后续的了解中再进行一一对应,进行完善。

参考资料:

https://developers.google.com/web/updates/2018/09/inside-browser-part3

https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Speculative_parsing

https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction

https://blog.sessionstack.com/how-javascript-works-the-rendering-engine-and-tips-to-optimize-its-performance-7b95553baeda