简略图解:输入 url 到出现页面,浏览器做了什么?
应该有很多前端开发人员都思考过这么一个问题:从输入 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 到出现页面,浏览器做了什么?的更多相关文章
- 关于浏览器,从输入URL到呈现页面过程!(主讲TCP/IP协议)
一.文本对话--从请求到响应 我们在浏览器中输入一个 URL,回车之后便会在浏览器中观察到页面内容.实际上这个过程是: (1)浏览器向网站所在的服务器发送了一个 Request(请求) (2)网站服务 ...
- 浏览器输入URL到响应页面的全过程
B/S网络架构从前端到后端都得到了简化,都基于统一的应用层协议HTTP来交互数据,HTTP协议采用无状态的短链接的通信方式,通常情况下,一次请求就完成了一次数据交互,通常也对应一个业务逻辑,然后这次通 ...
- 计算机网络【6】—— 从浏览器输入URL到显示页面发生了什么
当在浏览器地址栏输入网址,如:www.baidu.com后浏览器是怎么把最终的页面呈现出来的呢?这个过程可以大致分为两个部分:网络通信和页面渲染. 一.网络通信 互联网内各网络设备间的通信都遵循TCP ...
- 从浏览器地址栏输入url到显示页面的步骤
在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期 HTTP1.1增加了Cache-Cont ...
- 从浏览器地址栏输入url到显示页面的步骤(以HTTP为例)
在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 如果资源未缓存,发起新请求 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证. 检验 ...
- 输入URL到展现页面的全过程
最近在看一本关于网络协议的书<图解HTTP> 当我们在浏览器的地址栏输入 http://www.pwstrick.com ,然后回车,回车这一瞬间到看到页面到底发生了什么呢? 1. 域名 ...
- 输入URL地址到页面加载完成 过程
在浏览器的地址栏中输入URL地址"http://www.gacl.cn:8080/JavaWebDemo1/1.jsp"去访问服务器上的1.jsp这个web资源的过程 1.浏览器根 ...
- HTTP:地址栏输入url到显示页面的步骤
在浏览器地址栏输入URL 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤 如果资源未缓存,发起新请求 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证. 检验 ...
- 用户在浏览器输入URL回车之后,浏览器都做了什么
在直接列出执行的步骤之前先来普及几个知识,相信了解完这些知识之后会对前后端的交互有更深入的理解. 1.TCP连接 TCP:Transmission Control Protocol, 传输控制协议,是 ...
随机推荐
- <jsp:param>传递参数,出现乱码问题
今天在学习<jsp:forward>和<jsp:param>时,用<jsp:param>传递参数时,出现乱码问题,部分代码如下: 1 <jsp:forward ...
- Mybatis代码自动生成(含测试)
一.建立数据库 create database shixun; use shixun; create table user( id int primary key auto_increment , u ...
- 利用C语言判定用户输入数据从而给出结果(利用判定用户体重范围)同求最优解!!!
例子: 要求:医务工作者通过广泛的调查和统计分析,根据成人的身高与体重因素给出了按"体质指数"进行判断的方法,具体如下: 体质指数t=体重 w/(身高h)2(w的单位为kg,h的单 ...
- 『与善仁』Appium基础 — 2、常用Android模拟器的安装
目录 1.Android Virtual Devices模拟器 2.Genymotion模拟器 (1)Genymotion模拟器下载 (2)模拟器Genymotion安装 (3)Genymotion模 ...
- 初探SpringRetry机制
重试是在网络通讯中非常重要的概念,尤其是在微服务体系内重试显得格外重要.常见的场景是当遇到网络抖动造成的请求失败时,可以按照业务的补偿需求来制定重试策略.Spring框架提供了SpringRetry能 ...
- 计算机毕业设计选题大合集,含ssm,springboot,小程序,php,python
1基于springboot医院急诊系统 2基于springboot校园闲置物品租售系统 3基于springboot校园闲置物品交易网站 4基于springboot图书网站 5基于springboot外 ...
- Java数据库分表与多线程查询结果汇总
今天接到一个需求:要对一个物理分表的逻辑表进行查询统计.而数据库用的是公司自己研发的产品,考虑的到公司产品的特点以及业务的需求,该逻辑表是按年月进行分表的,而非分区.我们来看一下,在按时间段进行查询统 ...
- 第二十五篇 -- QTreeWidget右击菜单的实现
效果图: 自己画一个ui,如图,前面已经讲过怎么用Qt Designer画图了,现在就不赘述了. ui_play.py # -*- coding: utf-8 -*- # Form implement ...
- 误改win10下的windowsapps文件夹权限,导致自带应用闪退问题
在项目中,为了获得相关应用的具体位置(office的具体exe位置),修改了文件夹WindowsApps权限,导致所有自带应用打开闪退. 通过搜索相关资料,获得解决方法: 重置该文件的权限设置 ica ...
- C++调试总结
一.参考: 本文主要参考<C++编程调试秘笈>一书. 在编写C++代码时,我们不应该自己捕捉缺陷,而是由编译器和可执行代码为我们做这些事情,该书便提供了这样的一个思考.作者以"调 ...