应该有很多前端开发人员都思考过这么一个问题:从输入 URL 到页面加载完成,中间都做发生了什么?

这个问题涉及的面非常广,每个涉及的点又很深入。从触屏/键盘如何到 CPU?CPU 如何到系统内核?如何从操作系统 GUI 到浏览器?浏览器如何向网卡发送数据?数据如何从本机网卡发送到服务器?服务器接收数据后如何处理?服务器返回数据后浏览器如何处理?浏览器如何将页面展现出来?等等等等,每一个过程都包含了大量且深入的知识体系,很难一以贯通。

但作为前端开发人员,浏览器是我们的主要工具之一,浏览器是如何将页面展现出来的则是我们更关注的部分。因此本文就从一些基本流程来简要描述这个过程。

从上面这个图中可以发现,虽然使用的 Javascript 是单线程语言,但浏览器本身是多进程的。

但是这并不是从一而终的状态,而是浏览器从早期的单进程结构逐渐发展发展而来。现代浏览器各进程根据负责的功能不同,分为浏览器进程、渲染器进程、网络进程、GPU 进程、缓存进程、插件进程等等。为了更好的理解浏览器页面的呈现过程,我们以最主流的 Chrome 为例,简要的说明一下各个进程的大致职能:

  • 浏览器进程: 负责控制界面展示、用户交互、子进程管理等功能。

  • 渲染器进程: 负责将 HTML\CSS\JS 转化为用户可以与之交互的网页。渲染引擎如 webkit、blink 和 JS 引擎 V8 都是在该进程之中。

  • GPU 进程: GPU 进程原本是为了实现 3D CSS 效果,但是随后页面、Chrome 的 UI 都采用 GPU 来绘制,是 GPU 成为了重要需求,于是增加了 GPU 进程。

  • 网络进程: 负责页面的网络资源加载。

  • 插件进程:负责插件的运行,由于插件可能崩溃,需要插件进程其他进程隔离。注意,插件并不是我们常用的浏览器拓展,plugin 和 extension 是不同的。

  • 缓存进程:负责处理页面资源缓存和清理。

我们本次需要重点关注的是渲染器进程。

回到问题,当我们在浏览器地址栏输入地址时,浏览器进程的 UI 线程会捕捉输入内容,如果访问的是网址,那么 UI 线程会启动一个网络线程来构建请求(这里我们暂时不考虑缓存,缓存又是另外一个故事了),它请求 DNS 进行域名解析然后连接服务器获取数据。如果我们输入的是关键词,浏览器则使用默认配置的搜索引擎来搜索。在获取到数据并通过安全校验后,网络线程会通知 UI 线程数据准备完毕,然后UI线程创建一个渲染器进程来进行页面的渲染,并将数据通过 IPC 管道传递给渲染器进程。

至此,我们的主角渲染器进程登场!

解析 HTML

渲染器进程接收到的是一个 HTML,需要把 HTML 解析成 DOM 数据结构。因为直接的 HTML 字节流是无法被渲染引擎所理解的,必须转化成可以理解的内部结构。这个内部结构就是 DOM,DOM 提供了对 HTML 文档的结构化表述。在渲染引擎中,DOM 有三个层面的作用:

  • 从页面角度:DOM 是生成页面的基础数据结构。

  • 从 js 角度:DOM 提供了 js 操作的接口。通过这套接口,js 可以对 DOM 接口进行访问,从而使开发者拥有改变文档结构、样式、内容的能力。

  • 从安全角度:DOM 是 HTML 经过解析的内部数据结构,它将 web 页面和 js 链接起来,并过滤了一些不安全的内容。

渲染器进程内部使用 HTML Parser 将 HTML 解析成 DOM 结构。需要注意的是,HTML 解析器不会等待整个 HTML 文档加载完毕再去解析,而是加载多少了多少 HTML,就解析多少。

那么 HTML 字节流是如何转换成 DOM 的呢?

其实和 V8 解析 js 类似,也是做词法分析,通过分词器将字节流成功成一个个 token,包括 Tag token 和文本 token。HTML 解析器维护了一个 token 栈结构,token 会按照对应顺序入栈出栈,然后将 token 解析成 DOM 节点,并将 DOM 节点添加进 DOM 树中。

前面提到生成 DOM 可以过滤一些不安全内容。这主要是渲染引擎中的一个名为XSSAuditor 安全检查模块实现的。它会监测词法安全,在分词器解析出 token 之后,检查这些模块是否引用了外部脚本,是否符合 CSP 规范,是否存在跨站点请求等。如果出现不符合规范的内容。XSSAuditor 会对该脚本或下载任务进行拦截。

DOM 树在构建过程中会创建 document 对象,然后以 document 为根节点的 DOM 树不断修改向其中添加新的元素。

解析 CSS

前面已经将 HTML 解析成 DOM 树了,但是光拥有 DOM 树还不足以让我们知道页面的样貌。因为我们肯定会为页面设置一些样式。因此主进程还会解析页面中的 CSS 从而确定每个 DOM 节点的计算样式(computed style)。

CSS 的样式来源主要有三个:

  • 通过 link 引用的外部 CSS 文件

  • 使用

简略图解:输入 url 到出现页面,浏览器做了什么?的更多相关文章

  1. 关于浏览器,从输入URL到呈现页面过程!(主讲TCP/IP协议)

    一.文本对话--从请求到响应 我们在浏览器中输入一个 URL,回车之后便会在浏览器中观察到页面内容.实际上这个过程是: (1)浏览器向网站所在的服务器发送了一个 Request(请求) (2)网站服务 ...

  2. 浏览器输入URL到响应页面的全过程

    B/S网络架构从前端到后端都得到了简化,都基于统一的应用层协议HTTP来交互数据,HTTP协议采用无状态的短链接的通信方式,通常情况下,一次请求就完成了一次数据交互,通常也对应一个业务逻辑,然后这次通 ...

  3. 计算机网络【6】—— 从浏览器输入URL到显示页面发生了什么

    当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染. 一.网络通信 互联网内各网络设备间的通信都遵循TCP ...

  4. 从浏览器地址栏输入url到显示页面的步骤

      在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期 HTTP1.1增加了Cache-Cont ...

  5. 从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)

    在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 如果资源未缓存,发起新请求 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证. 检验 ...

  6. 输入URL到展现页面的全过程

    最近在看一本关于网络协议的书<图解HTTP> 当我们在浏览器的地址栏输入 http://www.pwstrick.com ,然后回车,回车这一瞬间到看到页面到底发生了什么呢? 1.  域名 ...

  7. 输入URL地址到页面加载完成 过程

    在浏览器的地址栏中输入URL地址"http://www.gacl.cn:8080/JavaWebDemo1/1.jsp"去访问服务器上的1.jsp这个web资源的过程 1.浏览器根 ...

  8. HTTP:地址栏输入url到显示页面的步骤

    在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 如果资源未缓存,发起新请求 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证. 检验 ...

  9. 用户在浏览器输入URL回车之后,浏览器都做了什么

    在直接列出执行的步骤之前先来普及几个知识,相信了解完这些知识之后会对前后端的交互有更深入的理解. 1.TCP连接 TCP:Transmission Control Protocol, 传输控制协议,是 ...

随机推荐

  1. leetcode第156场周赛5205

    思路分析:先用哈希表统计各个数字的次数,再将每个值放进set集合中,之后如果有重复得,说明比原个数少了,如果都是独一无二的,那么个数是相同的 这波把collection集合,强转成set是真的灵性.想 ...

  2. 《PHP安全编程系列》系列分享专栏

    PHP安全编程系列收藏夹收藏了有关PHP安全编程方面的知识,对PHP安全编程提供学习参考 <PHP安全编程系列>已整理成PDF文档,点击可直接下载至本地查阅https://www.webf ...

  3. WPF项目升级sqlite-net-pcl时遇到Library e_sqlite3 not found的问题解决办法记录

    项目中为了方便的存储本地数据,使用了SQLite数据库作为数据存储,再设计时DB.models引用了sqlite-net-pcl,那么项目再升级sqlite-net-pc 1.7.335l版本后后,遇 ...

  4. create-react-app 入门学习

    全局安装 create-react-app npm install create-react-app -g 创建项目 在全局安装了create-react-app 后 创建项目,如果按照下面的第一种办 ...

  5. 题解 CF311B Cats Transport

    前置芝士:斜率优化  剥下这道题的外壳,让它变为一道裸的斜率优化. 很容易想到状态,但复杂度显然过不去,也没有单调性,只能自己创造. 令 $$c[i] = t - sum[i],sum[i] = \s ...

  6. C语言:自增 自减

    一个整数类型的变量自身加 1 可以这样写: a = a + 1; 或者 a += 1; 不过,C语言还支持另外一种更加简洁的写法,就是: a++; 或者 ++a; 这种写法叫做自加或自增,意思很明确, ...

  7. .netcore第三方登录授权:10分钟急速接入

    前言 很多对外应用的开发都考虑接入第三方登录来提高用户的体验感,避免用户进行繁琐的注册登录(登录后的完善资料必不可免). 而QQ.微信.支付宝.淘宝.微博等应用就是首选目标(无他,用户群体大,支持发开 ...

  8. 简单设计一个onedata指标管理体系

    以阿里云的maxcompute的数据仓库架构为例, 从上往下定义, dwp的数据,来源是dws+dim,最主要是dws.这里不讨论dim的作用. dws的数据来源于dwd. dwd的数据来源于ods. ...

  9. EasyUI学后总结第一集

    1,创建Easyui组件-使用html还是使用js方式? 如果在创建Easyui组件的时候,组件再被更改,那么属于静态组件,对于静态组件不要使用js方式创建--会增加js代码量. 如果创建的Easyu ...

  10. python之数据驱动ddt操作(方法二)

    import unittestfrom ddt import ddt,unpack,datafrom selenium import webdriverfrom selenium.webdriver. ...