Skip to content

基本渲染流程

流程概述

  • 浏览器通过请求获得一个 HTML 文本。
  • 渲染线程解析 HTML 文本, 构建 DOM 树
  • 浏览器解析 HTML 的同时,如果遇到外联样式,则下载并构建样式规则(stytle rules)。若遇到 Javascript 脚本,则会下载并执行脚本。
  • DOM 树和样式规则渲染完成之后,渲染线程将两者合并成渲染树。 render tree
  • 渲染线程开始对渲染树进行基本的布局, 生成布局树。 layout tree
  • 渲染线程对布局树进行绘制,生成绘制记录
  • 渲染线程对布局树进行分层,分别栅格化每一层并得到合成帧
  • 渲染线程将合成帧发送给 GPU 进程将图像绘制到页面中。

详细描述

  • 解析 HTML: 浏览器从服务器获取 HTML 文件,并对其进行解析,构建文档对象模型(DOM)树。DOM 树表示网页的结构和内容。

    • 浏览器从服务器获取 HTML 文件,并按照指定的编码方式解析文件内容
    • 解析过程中, 浏览器构建文档对象模型 DOM 树, 表示网页的结构和内容。
    • 可以优化的点:
      • 减少 HTML 文件的大小,通过压缩和合并代码,使用服务器端压缩技术等。(如开启 GZIP)
      • 使用有效的 HTML 结构, 避免冗余的标签属性,优化 DOM 树的构建。
  • 解析 CSS:浏览器解析 CSS 文件,构建 CSS 对象模型(CSSOM)树。CSSOM 树表示样式规则和样式属性。

    • 浏览器解析 CSS 文件,构建 CSS 对象模型(CSSOM)树,表示样式规则和样式属性。
    • 解析过程中,浏览器会处理选择器匹配、继承和层叠等规则。
    • 可以优化的点:
      • 减少 CSS 文件的大小,例如通过压缩和合并代码、使用 CSS 预处理器(如 Sass、Less)等。
      • 避免使用复杂的选择器,以减少匹配和计算的复杂度。
      • 使用样式继承和层叠规则,避免重复定义相同的样式属性。
  • 合成渲染树:浏览器将 DOM 树和 CSSOM 树合并为渲染树(Render Tree)。渲染树只包含需要显示的页面内容,并考虑了元素的样式属性和布局。

    • 浏览器将 DOM 树和 CSSOM 树合并为渲染树(Render Tree),该树包含需要显示的页面内容,并考虑了元素的样式属性和布局。
    • 渲染树不包含不需要显示的元素(如隐藏的元素或不可见的元素)。
    • 可以优化的点
      • 避免在渲染树中包含不必要的元素,使用 CSS 的显示和隐藏属性来控制元素的可见性。
      • 避免频繁修改 DOM 结构和样式属性,因为每次修改都需要重新构建渲染树,影响性能。
  • 布局(Layout):渲染树中的元素根据其盒模型(尺寸、位置、边距等)进行布局计算。布局过程确定元素在页面上的准确位置。

    • 渲染树中的元素根据其盒模型(尺寸、位置、边距等)进行布局计算,确定元素在页面上的准确位置。
    • 布局过程涉及计算元素的大小和位置,处理盒模型属性、浮动、定位等。
    • 优化点:
      • 减少布局的复杂性,避免过多的嵌套和复杂的盒模型属性,以提高布局的性能。
      • 避免频繁修改布局相关的属性,例如盒模型属性、定位属性等,以减少不必要的布局计算。
  • 绘制(Painting):浏览器根据渲染树和布局信息将页面内容绘制到屏幕上。这包括确定元素的绘制顺序、应用样式和绘制元素的边框、背景、文本等。

    • 浏览器根据渲染树和布局信息将页面内容绘制到屏幕上,包括绘制元素的边框、背景、文本等。
    • 绘制过程可以使用硬件加速,利用图形卡或操作系统的图形库来提高性能。
    • 优化点
      • 减少不必要的绘制操作,例如使用 CSS 的 will-change 属性来标记即将发生变化的元素,避免频繁的绘制操作。
      • 使用 CSS 的变换和过渡效果,利用硬件加速来优化动画和过渡的性能。
  • 栅格化(Rasterization):浏览器将绘制好的页面内容转换为位图(栅格图像)。这是将矢量图形转换为屏幕上可显示的像素的过程。

    • 浏览器将绘制好的页面内容转换为位图(栅格图像),将矢量图形转换为屏幕上可显示的像素。
    • 栅格化过程包括将绘制内容分割为小的图块(Tiles),然后将每个图块转换为位图。
    • 优化点:
      • 减少栅格化的复杂性,例如通过减少图层数量、使用合理的图块大小等来提高栅格化的性能。
  • 合成(Compositing):如果页面中有多个图层(例如,使用 CSS 属性 transform 或 opacity 创建的图层),浏览器将图层合成为最终的页面图像。

    • 如果页面中有多个图层(例如,使用 CSS 属性 transform 或 opacity 创建的图层),浏览器将图层合成为最终的页面图像。
    • 合成过程包括将各个图层按照合成顺序进行组合,形成最终的图像。
    • 优化点:
      • 减少图层的数量和复杂度,避免过多的合成操作,以提高合成的性能。
  • 显示(Display):最终的渲染图像通过图形卡或操作系统的图形库显示在屏幕上。

    • 最终的渲染图像通过图形卡或操作系统的图形库显示在屏幕上,呈现给用户。
    • 显示过程涉及将位图发送到屏幕上的显示设备,以实现可视化效果。
    • 优化点:
      • 优化图形卡和操作系统的配置,确保其能够有效地处理和显示渲染图像。
      • 避免频繁的页面刷新,例如通过使用动画和过渡的合理帧率来减少刷新操作。

常见优化技巧

  1. 减少网络请求: 合并和压缩文件,使用缓存资源,延迟加载非关键资源。
  2. 使用 CSS Sprites: 将多个小图标合并为一个大图,减少图像的下载次数。
  3. 使用异步加载和延迟执行: 奖 javascript 文件放在页面的地步,使用 async 或 defer 等属性加载 script 脚本。
  4. 最小化重绘和重排: 避免频繁修改 DOM 和样式属性,使用批量操作或者样式优化等技术。
  5. 开启硬件加速: 利用 css 的变换和过度的效果,使用 will- change 等属性,提高动画和过度属性。
  6. 图层优化: 将频繁的变化的元素放在单独的图层中,避免过多 的合成操作等。
  7. 响应式设计: 根据设备和屏幕的大小优化布局和样式,提供更好的用户体验。

服务端渲染 SSR

服务端渲染就是在浏览器请求页面 URL 的时候,服务端将我们需要的 HTML 文本组装好,并返回给浏览器,这个 HTML 文本被浏览器解析之后,不需要经过 JavaScript 脚本的下载过程,即可直接构建出我们所希望的 DOM 树并展示到页面中。这个服务端组装 HTML 的过程就叫做服务端渲染 SSR

客户端渲染 CSR

大部分 WEB 应用都是使用 JavaScript 框架(Vue、React、Angular)进行页面渲染的,页面中的大部分 DOM 元素都是通过 Javascript 插入的。也就是说,在执行 JavaScript 脚本之前,HTML 页面已经开始解析并且构建 DOM 树了,JavaScript 脚本只是动态的改变 DOM 树的结构,使得页面成为希望成为的样子,这种渲染方式叫动态渲染,也就是平时我们所称的客户端渲染 CSR(client side render)

静态站点生成 SSG

与 SSR 的相同之处就是对应的服务端同样是将已经组合好的 HTML 文档直接返回给客户端,所以客户端依旧不需要下载 Javascript 文件就能渲染出整个页面,那不同之处又有哪些呢? 使用了 SSG 技术搭建出的网站,每个页面对应的 HTML 文档在项目 build 打包构建时就已经生成好了,用户请求的时候服务端不需要再发送其它请求和进行二次组装,直接将该 HTML 文档响应给客户端即可,客户端与服务端之间的通信也就变得更加简单 HTML 文档既然是在项目打包时就已经生成好了,那么所有用户看到的都只能是同一个页面,就像是一个静态网站一样,这也是这项技术的关键字眼——静态 每次更改内容时都需要构建和部署应用程序,所以其具有很强的局限性,不适合制作内容经常会变换的网站

渲染对比

相对于客户端渲染,服务端渲染和静态网点生成在浏览器请求 URL 之后得到的是一个带有数据的 HTML 文本,并不是一个 HTML 空壳。浏览器只需要解析 HTML,直接构建 DOM 树就可以了。而客户端渲染,需要先得到一个空的 HTML 页面,这个时候页面已经进入白屏,之后还需要经过加载并执行 JavaScript、请求后端服务器获取数据、JavaScript 渲染页面几个过程才可以看到最后的页面。特别是在复杂应用中,由于需要加载 JavaScript 脚本,越是复杂的应用,需要加载的 JavaScript 脚本就越多、越大,这会导致应用的首屏加载时间非常长,从而降低了体验感。

SSR 与 SSG 的选取,我们要从应用场景出发,到底是用户每次请求都在服务端重新组装一个 HTML 文档?还是在项目构建的时候就生成一个唯一的 HTML 文档呢?

无论是哪种渲染方式,一开始都是要请求一个 HTML 文本,但是区别就在于这个文本是否已经被服务端组装好了

客户端渲染还需要去下载和执行额外的 Javascript 脚本之后才能得到我们想要的页面效果,所以速度会比服务端渲染慢很多 服务端渲染得到的 HTML 文档就已经组合好了对应的文本,浏览器请求到之后直接解析渲染出来即可,不需要再去下载和执行额外的 Javasript 脚本,所以速度会比客户端渲染快很多 对于一些内容不经常变化的网站,我们甚至可以在服务端渲染的基础上予以改进,将每次请求服务端都渲染一次 HTML 文档改成总共就只渲染一次,这就是静态站点生成技术