在浏览器输入 URL到页面展示中间发生了什么?

马丁路德 等级 454 0 0

这个问题是前端的经典问题,从这个问题出发我们可以从根本上了解如何解决性能优化问题~

首先我们可以在开头大概了解下在浏览器输入 URL到页面展示,中间有哪些步骤:

  • 用户从浏览器进程里输入请求信息
  • 网络发起 URL 请求
  • 服务器响应 URL 请求之后,浏览器进程就要开始准备渲染进程了
  • 渲染进程准备好之后,需要先向渲染进程提交页面数据,我们称之为提交文档的阶段
  • 渲染进程接收完文档信息之后,开始解析页面和加载子资源,完成页面的渲染

接下来我们详细的了解下各个步骤干了些什么

1. 用户输入

首先用户在地址栏输入一个查询关键字的时候,地址栏会判断输入的是搜索内容还是请求 URL

  • 如果是搜索内容,地址栏会使用浏览器的默认搜索引擎,来合成新的带搜索关键字的 URL
  • 如果输入的内容符合 URL 的规则,比如输入的是 baidu.com ,那么地址栏会根据规则,把这段内容加上协议,合成完整的 URL,比如:www.baidu.com

当用户按下回车,浏览器开始加载 URL

2. URL 请求过程

这一步开始进入页面资源请求过程,首先网络进程会查找本地缓存是否缓存了该资源

  • 如果缓存了该资源,那么直接返回资源给浏览器进程
  • 如果在缓存中没有,直接进入网络请求流程,请求前第一步是进行 DNS 解析,以获取请求域名的服务器 IP 地址,如果进行的 HTTPS 请求协议,那么还需要建立 TLS 连接

接下来利用 IP 地址和服务器简历 TCP 连接,连接建立之后,浏览器会构建请求行、请求头等信息,并把该域名相关的 cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息

服务器收到请求信息后,会根据请求信息生成响应数据(包括响应行,响应头,响应体)等信息, 并发送给网络进程,等网络进程接受了响应行和响应头后,就开始解析响应头的内容。

在接收到服务器返回的响应头后,网络进程开始解析响应头,如果发现返回的状态码是 301 或者 302,那么说明服务器需要浏览器重定向到其他 URL。这时网络进程会从响应头的 Location 字段里面读取重定向的地址,然后再发起新的 HTTP 或者 HTTPS 请求,一切又重头开始了。

直到服务器的响应头状态码是 200,就可以继续往下处理该请求了

接下来就是对响应数据的类型处理,因为 URL 请求的数据类型,有时候是下载类型,有时候是正常的 HTML 页面,浏览器如何区分它们呢?

答案是 Content-Type,这个字段告诉浏览器服务器返回的是什么类型的响应体,然后浏览器根据 Content-Type 的值来决定如何显示响应体的内容。

比如:

  • Content-Type: text/html - 服务器的返回数据格式是 HTML 格式
  • Content-Type: application/octet-stream - 显示数据是字节流类型,通常情况下浏览器会按照下载类型来处理该请求

所以如果 Content-Type 的值被浏览器判断成下载类型,那么该请求会被提交给浏览器的下载管理器,同时 URL 请求的导航流程就此结束

如果是 HTML ,浏览器会继续进行导航流程,由于 Chrome 的页面渲染是运行在渲染流程中的,所以接下来就要准备渲染进程了

3. 准备渲染进程

通常情况下,Chrome 会为每个页面分配一个渲染进程,但是对同一站点的情况就会共用一个进程(之前讲过)

渲染进程准备好之后,还不能立即进入文档解析状态,因为此时的文档数据还在网络进程中,并没有提交给渲染进程,所以下一步就到了提交文档阶段。

4. 提交文档

这里的文档,指的是 URL 请求的响应体数据

  • 提交文档的消息是由浏览器进程发出的,渲染进程接收到提交文档的消息后,会和网络进程建立传输数据的通道
  • 等文档数据传输完成之后,渲染进程会返回确认提交的消息给浏览器进程
  • 浏览器接收到确认提交的消息后,才会更新浏览器界面状态,包括了安全状态、地址栏状态的 URL、前进后退的历史状态,并更新 Web 页面

这也就解释了为什么在浏览器输入一个地址后,之前的页面没有马上消失,二是要加载一会才回更新页面。 到了这里,一个完整的导航流程就走完了,马上进入渲染阶段

5. 渲染阶段

一旦文档被提交,渲染进程就要开始页面解析和子资源加载了,这就进入到了渲染流程

我们知道页面的三大要素:

  • HTML - 由标签和文本组成,负责页面的结构显示
  • CSS - 层叠样式,由选择器和样式组成 - 负责文本的样式
  • JavaScript - 负责页面的逻辑交互

由于渲染机制过于复杂,所以渲染模块在执行过程中会被划分为很多子阶段,输入的 HTML\CSS\JavaScript 经过这些子阶段,最后输出像素,这样的处理流程叫做渲染流水线,大致如图所示

在浏览器输入 URL到页面展示中间发生了什么?

按照渲染的时间顺序,流水线可以氛围如下几个子阶段:

构建 DOM 树 ---> 样式计算 ---> 布局阶段 ---> 分层 ---> 绘制 ---> 分块 ---> 光栅化 ---> 合成

在每个阶段都会有三个内容:

  • 开始每个子阶段都有其输入的内容
  • 每个子阶段都有其处理过程
  • 最终每个子阶段都会生成输出内容

那么接下来我们一步步来了解这些子阶段

构建 DOM 树

由于浏览器无法直接理解和使用 HTML,所以需要将 HTML 转换为浏览器可以理解的解构 - DOM 树 树结构如下所示,其中的每个点我们叫做节点

在浏览器输入 URL到页面展示中间发生了什么?

我们可以在开发者工具的控制台中,输入 document 得到该网页的完整 DOM 结构, 如下图所示

在浏览器输入 URL到页面展示中间发生了什么?

DOM 和 HTML 内容几乎是一样的,但是和 HTML 不同的是,DOM 是保存在内存中的树状结构,可以通过 JavaScript 来查询或者修改其内容

所以构建 DOM 的输入内容是一个 HTML 文件,经由 HTML 解析器解析,最终输出树状结构的 DOM

这样已经生成好 DOM 树了,但是 DOM 节点的样式还未知,所以下一步就是样式计算

样式计算

我们知道 CSS 样式来源有三种:

  • link 引用的外部 CSS
  • 标记内的 CSS
  • 元素的 style 属性内嵌的 CSS

和 HTML 文件一样,浏览器并不能直接理解这些纯文本的 CSS 样式,所以当渲染引擎接收到 CSS 文本的时候,会执行一个转换操作,把 CSS 转换成浏览器可以理解的:styleSheets

在控制台中,输入 document.styleSheets 得到该网页的 styleSheets ,如下图所示

在浏览器输入 URL到页面展示中间发生了什么?

这个图里面就包含了我们刚刚说到的三种样式来源 接下来浏览器就会把样式表中的属性进行标准化转换(例如 em/rem -> px)

在浏览器输入 URL到页面展示中间发生了什么?

转换示例如上图所示

转换完成之后,就下来就需要计算 DOM 树种每个节点的样式属性了,那么如何来进行计算呢?

这就涉及到了 CSS 的继承规则和层叠规则

  • CSS 继承
    • CSS 继承就是每个节点都会包含父节点有的样式(比如 body 节点设置了 font-size:18px; 那么 body 下面的子节点的 font-size 都是18)
    • 在开发者工具控制台的 computed 中,我们可以查看样式来源,可以看到具体的某些样式是来自样式文件还是 UserAgent 样式表(浏览器的默认样式)
  • 层叠样式规则
    • 层叠是 CSS 的一个基本特征,它定义了如何合并来自多个源的属性值的算法

样式计算阶段的目的是为了计算出 DOM 节点中每个元素的具体样式,在计算过程就需要遵循 CSS 继承和层叠两个规则

这个阶段最终输出的是每个 DOM 节点的样式,并且保存在 ComputedStyle 的结构中。

布局阶段

到了这个阶段,我们有了 DOM 树和 DOM 数中元素的样式,但是呢这还不足以显示页面,因为我们还不知道 DOM 元素的几何位置信息

那么接下来就要计算出 DOM 树中可见元素的几何位置,这个计算过程叫做布局

1. 创建布局树

在 DOM 树中可能会有很多不可见的元素,比如 head 标签和一些有 display:none 的属性,所以在显示前,我们还要额外构建一棵只包含可见元素的布局树 我们可以结合下图来看看布局树的构造过程:

在浏览器输入 URL到页面展示中间发生了什么? 从上图可以看出来,DOM 树种所有不可见的元素都没有包含到布局树中

为了构建布局树,浏览器大体上完成了下面这些工作

  • 遍历DOM 树中所有可见节点,并把这些节点加到布局中
  • 不可见的节点会被忽略掉,如 head 标签下面的全部内容,以及 display:none 的元素也不会被包含进布局树

2. 布局计算

现在我们有了一棵完整的布局树,接下来就是计算布局树中节点的坐标位置(计算过程暂时略过,比较复杂)

在执行布局操作的时候,会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局 阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫 LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单。

分层

有了布局树之后,是不是就可以开始绘制页面了呢?答案当然是 false 因为页面中往往有很多复杂的效果,比如 3D 变换,页面滚动、z-index 的 Z 轴排序等等,为了更方便的实现这些效果 渲染引擎还需要为特定的节点生成专用的涂层,并生成一棵对应的图层树,正是各种各样的图层叠加在一起构成了最终的页面

打开 Chrome 的“开发者工具”,选择“Layers”标签,就可以可视化页面的分层情况,

到这里我们就知道浏览器的页面实际上被分成了很多图层,这些图层叠加合成了最终的页面,我们可以来看看这些图层和布局树节点之间的关系:

在浏览器输入 URL到页面展示中间发生了什么?

通常情况下,并不是布局树的每个节点都包含一个图层,如果一个节点没有对应的图层,那么这个节点就舒服父节点的图层。

不管怎么样,最种每个节点都会直接或间接的属于一个层。

那么这里有个问题,在什么样的条件下,渲染引擎才会为特定的节点创建新的图层呢?

  • 拥有层叠上下文属性的元素会被提升为单独的一层(position:fixed / z-index / filter:blue(5px) / opacity: 0.5 等)
  • 需要剪裁 (clip) 的地方也会被单独创建图层(比如一个 div 长宽只有 200,但是内容很多,那么多余的部分就会出现被裁剪,这种情况渲染引擎会为文字部分单独创建一层,如果出现滚动条,那么滚动条也是一个单独的层)

所以如果元素有了层叠上下文属性或者需要被剪裁,满足任意一点就会被提升为单独的图层

图层绘制

完成了图层树的创建之后,渲染引擎会对图层树中的每个图层进行绘制(按照基本回话顺序,比如先底色再画图形的顺序,所以是低层级到高层级的绘制) 我们可以打开开发者工具的 Layers 标签,选择 document 层,就可以实际体验下绘制列表。

栅格化

绘制列表只是用来记录绘制顺序和绘制指令的列表,而实际上绘制操作是由渲染引擎中的合成线程来完成的。 我们可以结合下图来看下渲染主线程和合成线程之间的关系:

在浏览器输入 URL到页面展示中间发生了什么?

当图层的绘制列表准备好之后,主线程会把该绘制列表提交(commit)给合成线程,合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图

合成线程发送绘制图块命令DrawQuad给浏览器进程,浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上

总结

  • 浏览器不能直接理解 HTML 数据,所以第一步需要将其转换为浏览器能够理解的 DOM 树结构;
  • 生成 DOM 树后,还需要根据 CSS 样式表,来计算出 DOM 树所有节点的样式;
  • 最后计算 DOM 元素的布局信息,使其都保存在布局树中。

如果下载 CSS 文件阻塞了,会阻塞 DOM 树的合成吗?会阻塞页面的显示吗?

不会阻塞dom树的构建,原因Html转化为dom树的过程,发现文件请求会交给网络进程去请求对应文件,渲染进程继续解析Html。 会阻塞页面的显示,当计算样式的时候需要等待css文件的资源进行层叠样式。资源阻塞了,会进行等待,直到网络超时,network直接报出相应错误,渲染进程继续层叠样式计算

6. 渲染完成

页面生成完成后,渲染进程会发送一个消息给浏览器进程,浏览器接收到消息后,会停止标签图标上的加载动画。这样,一个完整的页面就生成了。

本文转自 https://juejin.cn/post/6939723201597407263,如有侵权,请联系删除。

收藏
评论区

相关推荐

《前端实战总结》之使用纯css实现网站换肤和焦点图切换动画
今天我们来继续复盘一些工作中常用的css技巧和知识,以便我们可以更加优雅的用css实现富有动感的网站. 你将收获 网站换肤设计方案介绍 :target伪类介绍和用法以及如何使用css实现网站换肤 transition动画以及如何用纯css实现焦点图动画 效果展示 1.网站换肤 (https://imghelloworld.ossc
巧用css圆角实现有点意思的加载动画
作为一名前端工程师, 需要对css技巧有充分的研究和了解, 接下来笔者将会带大家一起掌握如何用css的圆角属性来实现有点意思的加载动画. 如果想学习更多css实用技巧, 可以参考笔者以下的文章: <div style"display:flex; flexwrap:wrap; alignitems: center;" <a href"https:/
2. web前端开发分享-css,js进阶篇
2. web前端开发分享css,js进阶篇 一,css进阶篇:   等css哪些事儿看了两三遍之后,需要对看过的知识综合应用,这时候需要大量的实践经验, 简单的想法:把qq首页全屏另存为jpg然后
CSS Modules 解决 react 项目 css 样式互相影响的问题
CSS Modules 解决 react 项目 css 样式互相影响的问题 CSS Modules 解决 react 项目 css 样式互相影响的问题 (http
容易被忽略的5个HTML技巧
对于所有 Web 开发人员来说,无论你选择的是哪种框架或后端语言,都需要大量使用 HTML(超文本标记语言)。 各种框架和编程语言可能会此消彼长,但 HTML 永不会过时。只是,就算 HTML 的应用如此广泛,这种语言中还是有不少多数开发人员都不了解的标签和属性。 而且,尽管市面上有各种模板引擎(例如 Pug)可用,但你仍然需要对 HTML 和 CSS
一篇文章带你了解css z-index(重叠顺序)
div csszindex层重叠顺序 div层、span层等html标签层重叠顺序样式zindex,平时CSS使用较少,但也会难免会碰到CSS zindex使用。 从基础语法到应用案例教程讲解学习zindex。 一、zindex语法与结构 zindex 跟具体数字 div{ zindex:100 } 注意:zindex的
30个前端开发人员必备的顶级工具
在本文中,我为前端Web开发人员汇总了30种顶级工具,从代码编辑器和代码游乐场到CSS生成器,JS库等等。 (https://imghelloworld.osscnbeijing.aliyuncs.com/2e7966318084a45d05a0926cbd749a02.png) 目录 CSS代码生成器 CSS3 Generator
在浏览器输入 URL到页面展示中间发生了什么?
这个问题是前端的经典问题,从这个问题出发我们可以从根本上了解如何解决性能优化问题 首先我们可以在开头大概了解下在浏览器输入 URL到页面展示,中间有哪些步骤: 用户从浏览器进程里输入请求信息 网络发起 URL 请求 服务器响应 URL 请求之后,浏览器进程就要开始准备渲染进程了 渲染进程准备好之后,需要先向渲染进程提交页面数据,我
有关CSS预编译、管理工具和网络安全的相关面试题
我经常会听到一些想入行前端的人问,前端开发需要学习哪些技术?其实,除了核心的HTML、CSS、JavaScript技术外,像CSS预编译、前端框架,如Vue,React、Node、Angular;代码管理工具,如git,代码编辑器,sublime text,还有测试,网络安全等相关技术也是需要会一些。当然要求可能不会那么高,但至少要懂一些。所有今天准备了一些
VUE3(七)vue项目抽离.vue文件中的js、css代码
平常再做开发的时候,一般情况下不会将html,js,css代码写到一个文件中。基本上都会写在各自对应的文件中,然后再引入即可。那么在VUE中我们如何抽离vue文件中的js,与css代码呢? 1:抽离javascriptHome.vue<template <div <div :style"{ padding: '24px', back
Vue进阶(幺柒陆):CSS预编译语言Sass、Scss、Less和Stylus
什么是CSS预处理器CSS预处理器定义了一种新的语言,它的基本思想是,用一种专门的编程语言,进行网页样式设计,然后再编译成正常的CSS文件。开发者只需要使用这种语言进行编码工作,减少枯燥无味的CSS代码
只听说过CSS in JS,怎么还有JS in CSS?
CSS in JS是一种解决css问题想法的集合,而不是一个指定的库。从CSS in JS的字面意思可以看出,它是将css样式写在JavaScript文件中,而不需要独立出.css、.less之类的文件。将css放在js中使我们更方便的使用js的变量、模块化、treeshaking。还解决了css中的一些问题,譬如:更方便解决基于状态的样式,更容易追溯依赖关
你可能不知道的10个CSS新功能(2021版)
多年来,CSS已经超越了背景颜色、边框、文本样式、边距和盒模型。现代CSS能够提供一系列的功能,而在过去,您需要JavaScript或变通方法来实现这些功能。 为了庆祝它在2021年取得的成就,在这篇文章中,我们想看看一些你可能不知道的令人惊叹的CSS新特性。我们将强调web设计人员和开发人员可以用现代CSS做的很酷的事情,讨论用例,浏览器支持,并给你一个
天哪!几行js代码就可以实现拳皇小游戏
前言今天,我们用原生JS实现一个拳皇人物位置控制的小效果。话不多说,我们赶紧来看下如何实现吧!效果(非静止八神)分别按W、S、A、D键可实现位置移动,并且效果真实。源码html与css很简单,主要是js中有几点需要注意的。<!DOCTYPE html <html lang"en" <head  <meta charset"UTF8"  <title游
如何提高CSS性能
结合现代网站的复杂性和浏览器处理 CSS 的方式,即使是适量的CSS也会成为设备受限、网络延迟、带宽或数据限制的瓶颈。因为性能是用户体验的一个至关重要的部分,所以必须确保在各种形状和尺寸的设备上提供一致的高质量体验,这也需要优化你的CSS。本篇文章将涵盖CSS会导致哪些性能问题,以及如何制作不妨碍人们使用的CSS的最佳实践。 目录 CSS是如何工作的?