一文摸透从输入URL到页面渲染的过程
一文摸透从输入URL到页面渲染的过程
从输入URL到页面渲染需要Chrome浏览器的多个进程配合,所以我们先来谈谈现阶段Chrome浏览器的多进程架构。
一、Chrome架构
目前Chrome采用的是多进程的架构模式,可分为主要的五类进程,分别是:浏览器(Browser)主进程、 GPU 进程、网络(NetWork)进程、多个渲染进程和多个插件进程;

- 浏览器进程。主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
- 渲染进程。核心任务是将
HTML、CSS和JavaScript转换为用户可以与之交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该进程中,默认情况下,Chrome会为每个Tab标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。 GPU进程。其实,Chrome刚开始发布的时候是没有GPU进程的。而GPU的使用初衷是为了实现3D CSS的效果,只是随后网页、Chrome的UI界面都选择采用GPU来绘制,这使得GPU成为浏览器普遍的需求。最后,Chrome在其多进程架构上也引入了GPU进程。- 网络进程。主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
- 插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响
了解了Chrome的多进程架构,就能够从宏观上理解从输入URL到页面渲染的过程了,这个过程主要分为导航阶段和渲染阶段。
二、导航阶段
Ⅰ.浏览器主进程
1.用户输入URL
- 1、浏览器进程检查
url,组装协议,构成完整的url,这时候有两种情况:- 输入的是搜索内容:地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的
URL。 - 输入的是请求
URL:地址栏会根据规则,给这段内容加上协议,合成为完整的URL;
- 输入的是搜索内容:地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的
- 2、浏览器进程通过进程间通信(
IPC)把url请求发送给网络进程;
Ⅱ.网络进程
2.URL请求过程
- 3、网络进程接收到
url请求后检查本地缓存是否缓存了该请求资源,如果有则将该资源返回给浏览器进程;
这里涉及到浏览器的缓存策略问题,有兴趣的可以上网查阅相关资料。
4、准备
IP地址和端口:进行DNS解析时先查找缓存,没有再使用DNS服务器解析,查找顺序为:- 浏览器缓存;
- 本机缓存;
hosts文件;- 路由器缓存;
ISP DNS缓存;DNS递归查询(本地DNS服务器 -> 权限DNS服务器 -> 顶级DNS服务器 ->13台根DNS服务器)
5、等待
TCP队列:浏览器会为每个域名最多维护6个TCP连接,如果发起一个HTTP请求时,这6个TCP连接都处于忙碌状态,那么这个请求就会处于排队状态;解决方案:- 采用域名分片技术:将一个站点的资源放在多个(
CDN)域名下面。 - 升级为
HTTP2,就没有6个TCP连接的限制了;
- 采用域名分片技术:将一个站点的资源放在多个(
6、通过三次握手建立
TCP连接:
- 第一次:客户端先向服务器端发送一个同步数据包,报文的
TCP首部中:标志位:同步SYN为1,表示这是一个请求建立连接的数据包;序号Seq=x,x为所传送数据的第一个字节的序号,随后进入SYN-SENT状态;
标志位值为
1表示该标志位有效。- 第二次:服务器根据收到数据包的
SYN标志位判断为建立连接的请求,随后返回一个确认数据包,其中标志位SYN=1,ACK=1,序号seq=y,确认号ack=x + 1表示收到了客户端传输过来的x字节数据,并希望下次从x+1个字节开始传,并进入SYN-RCVD状态;
这里要区分标志位
ACK和确认号ack;- 第三次:客户端收到后,再给服务器发送一个确认数据包,标志位
ACK=1,序号seq=x+1,确认号ack=y+1,随后进入ESTABLISHED状态;
服务器端收到后,也进入
ESTABLISHED状态,由此成功建立了TCP连接,可以开始数据传送;- 为什么要第三次挥手?避免服务器等待造成资源浪费,具体原因:
如果没有最后一个数据包确认(第三次握手),
A先发出一个建立连接的请求数据包,由于网络原因绕远路了。A经过设定的超时时间后还未收到B的确认数据包。于是发出第二个建立连接的请求数据包,这次网路通畅,
B的确认数据包也很快就到达A。于是A与B开始传输数据;过了一会
A第一次发出的建立连接的请求数据包到达了B,B以为是再次建立连接,所以又发出一个确认数据包。由于A已经收到了一个确认数据包,所以会忽略B发来的第二个确认数据包,但是B发出确认数据包之后就要一直等待A的回复,而A永远也不会回复。由此造成服务器资源浪费,这种情况多了
B计算机可能就停止响应了。- 第一次:客户端先向服务器端发送一个同步数据包,报文的
7、构建并发送
HTTP请求信息;8、服务器端处理请求;
9、客户端处理响应,首先检查服务器响应报文的状态码:
- 如果是
301/302表示服务器已更换域名需要重定向,这时网络进程会从响应头的Location字段里面读取重定向的地址,然后再发起新的HTTP或者HTTPS请求,跳回第4步。 - 如果是
200,就检查Content-Type字段,值为text/html说明是HTML文档,是application/octet-stream说明是文件下载;
- 如果是

- 10、请求结束,当通用首部字段
Conection不是Keep-Alive时,即不为TCP长连接时,通过四次挥手断开TCP连接:

- 第一次:客户端(主动断开连接)发送数据包给服务器,其中标志位
FIN=1,序号位seq=u,并停止发送数据; - 第二次:服务器收到数据包后,由于还需传输数据,无法立即关闭连接,先返回一个标志位
ACK=1,序号seq=v,确认号ack=u+1的数据包; - 第三次:服务器准备好断开连接后,返回一个数据包,其中标志位
FIN=1,标志位ACK=1,序号seq=w,确认号ack=u+1; - 第四次:客户端收到数据包后,返回一个标志位
ACK=1,序号seq=u+1,确认号ack=w+1的数据包。
由此通过四次挥手断开TCP连接。
详细过程参见:详解TCP连接的“三次握手”与“四次挥手”(上)
- 为什么要四次挥手?由于服务器不能马上断开连接,导致
FIN释放连接报文与ACK确认接收报文需要分两次传输,即第二次和第三次"挥手";
3.准备渲染进程
- 11、准备渲染进程:浏览器进程检查当前
url是否与之前打开了渲染进程的页面的根域名相同,如果相同,则复用原来的进程,如果不同,则开启新的渲染进程;
4.提交文档
- 12、提交文档:
- 渲染进程准备好后,浏览器向渲染进程发起“提交文档”的消息,渲染进程接收到消息后与网络进程建立传输数据的“管道”
- 渲染进程接收完数据后,向浏览器发送“确认提交”
- 浏览器进程接收到确认消息后更新浏览器界面状态:安全状态、地址栏
url、前进后退的历史状态、更新web页面

三、渲染阶段
在渲染阶段通过渲染流水线在渲染进程的主线程和合成线程配合下,完成页面的渲染;
Ⅲ.渲染进程

渲染进程中的主线程部分
5.构建DOM树
13、先将请求回来的数据解压,随后
HTML解析器将其中的HTML字节流通过分词器拆分为一个个Token,然后生成节点Node,最后解析成浏览器识别的DOM树结构。可以通过
Chrome调试工具的Console选项打开控制台输入document查看DOM树;
渲染引擎还有一个安全检查模块叫
XSSAuditor,是用来检测词法安全的。在分词器解析出来Token之后,它会检测这些模块是否安全,比如是否引用了外部脚本,是否符合CSP规范,是否存在跨站点请求等。如果出现不符合规范的内容,XSSAuditor会对该脚本或者下载任务进行拦截。
首次解析HTML时渲染进程会开启一个预解析线程,遇到HTML文档中内嵌的JavaScript和CSS外部引用就会同步提前下载这些文件,下载时间以最后下载完的文件为准。

6.构建CSSOM
14、
CSS解析器将CSS转换为浏览器能识别的styleSheets也就是CSSOM:可以通过控制台输入document.styleSheets查看;这里要考虑一下阻塞的问题,由于
JavaScript有修改CSS和HTML的能力,所以,需要先等到CSS文件下载完成并生成CSSOM,然后再执行JavaScript脚本,最后再继续构建DOM。由于这种阻塞,导致了解析白屏;
优化方案:
- 移除
js和css的文件下载:通过内联JavaScript、内联CSS;- 尽量减少文件大小:如通过
webpack等工具移除不必要的注释,并压缩js文件;- 将不进行
DOM操作或CSS样式修改的JavaScript标记上sync或者defer异步引入;- 使用媒体查询属性:将大的
CSS文件拆分成多个不同用途的CSS文件,只有在特定的场景下才会加载特定的CSS文件。
可以通过浏览器调试工具的Network面板中的DOMContentLoaded查看最后生成DOM树所需的时间;


7.样式计算
- 15、转换样式表中的属性值,使其标准化。比如将
em转换为px,color转换为rgb; - 16、计算
DOM树中每个节点的具体样式,这里遵循CSS的继承和层叠规则;可以通过Chrome调试工具的Elements选项的Computed查看某一标签的最终样式;

8.布局阶段
17、创建布局树,遍历
DOM树中的所有节点,去掉所有隐藏的节点(比如head,添加了display:none的节点),只在布局树中保留可见的节点。18、计算布局树中节点的坐标位置(较复杂,这里不展开);
9.分层
- 19、对布局树进行分层,并生成分层树(
Layer Tree),可以通过Chrome调试工具的Layer选项查看。分层树中每一个节点都直接或间接的属于一个图层(如果一个节点没有对应的层,那么这个节点就从属于父节点的图层)

10.图层绘制
- 20、为每个图层生成绘制列表(即绘制指令),并将其提交到合成线程。以上操作都是在渲染进程中的主线程中进行的,提交到合成线程后就不阻塞主线程了;

渲染进程中的合成线程部分

11.切分图块
21、合成线程将图层切分成大小固定的图块(256x256或者512x512)然后优先绘制靠近视口的图块,这样就可以大大加速页面的显示速度;

Ⅳ.GPU进程
12.栅格化操作
- 22、在光栅化线程池中将图块转换成位图,通常这个过程都会使用
GPU来加速生成,使用GPU生成位图的过程叫快速栅格化,或者GPU栅格化,生成的位图被保存在GPU内存中。

Ⅴ.浏览器主进程
13.合成与显示
- 23、合成:一旦所有图块都被光栅化,合成线程就会将它们合成为一张图片,并生成一个绘制图块的命令——“
DrawQuad”,然后将该命令提交给浏览器进程。
注意了:合成的过程是在渲染进程的合成线程中完成的,不会影响到渲染进程的主线程执行;
- 24、显示:浏览器进程里面有一个叫
viz的组件,用来接收合成线程发过来的DrawQuad命令,然后根据DrawQuad命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
到这里,经过这一系列的阶段,编写好的HTML、CSS、JavaScript等文件,经过浏览器就会显示出漂亮的页面了。
参考资料:浏览器工作原理与实践
一文摸透从输入URL到页面渲染的过程的更多相关文章
- 从浏览器输入URL到页面渲染的过程
零.背景 一个web安全工程师在学习web安全和web渗透时候,非常有必要了解整个WEB工作过程. 一.输入URL 这里是最基本的知识:URL是URI的一种实际应用,URI统一资源表示符,URL统一资 ...
- 从输入url到页面呈现的过程
从输入url到页面呈现的过程包括两个基本过程:网络通信和页面渲染 网络通信主要过程是 域名解析 -> TCP连接 -> HTTP请求 -> 服务端响应,返回HTML 页面渲染的主要过 ...
- 输入url到页面返回的过程
输入url后,你看到了百度的首页,那么这一切是如何发生的呢? 这个问题之前.最近.我想以后肯定还会被问到,或者问到这样的题目,如果在百度框里输入查询的字符串开始,是怎么返回你需要的东西呢. 那这什么个 ...
- 从输入URL到页面返回的过程详解
文章转自以为大神的博客;https://www.cnblogs.com/xianyulaodi/p/6547807.html#_labelTop 总结的很不错,看完收获颇多, 下面就是大神的文章,我只 ...
- 从输入url到页面展现的过程
先看一幅图:(下面的所有图我都进行拉伸压缩了 如果看不到 可以右键复制图片地址 然后到浏览器粘贴查看 不然显示不全图片) mac没有画图软件 不好意思 xmind做的 1. 输入网址 当 ...
- 从输入URL到页面渲染完成 -戈多编程
1.输入URL地址 2.浏览器根据域名查询IP地址 3.浏览器发送HTTP请求到web服务器 4.服务器返回一个永久重定向响应 5.浏览器会跟踪重定向地址 6.服务器处理请求 7.服务器返回一个HTM ...
- 面试题——分析从输入url到页面返回的过程(或者查询返回过程)
1. You enter a URL into the browser(输入一个url地址) 2.The browser looks up the IP address for the domain ...
- 输入URL到页面加载过程
URL(uniform resource location) : 统一资源定位符,用来作为互联网上各种资源的标识符,可理解为身份证号 . 注意点:浏览器为了保证安全性,设定了跨域保护策略, 即窗口之间 ...
- 输入URL到页面渲染
输入网址回车或者刷新页面到页面传染出来的整个流程 DNS 解析 HTTP三次握手 -> TCP/IP连接 浏览器发送请求 服务器返回请求的文件 (html) 浏览器渲染 1. DNS 解析 查找 ...
随机推荐
- vijos 1449 字符串还原
背景 小K是一位蔚蓝教主的崇拜者(Orz教主er),有一天,他收到了一封匿名信,信告诉了小K由于他表现出色,得到了一次当面Orz教主的机会,但是要当面Orz教主可不那么容易,不是每个人都有资格Orz教 ...
- Androidstudio实现一个简易的加法器——分享两种方法实现(日常作业练习)
Androidstudio实现一个简易的加法器——分享两种方法实现(日常作业练习) ...
- element UI中的tab切换栏
html代码:(用的是el-tab组件) <el-tabs v-model="activeIndex" type="border-card" @tab-c ...
- Hadoop集群搭建(四)~centos6.8关闭防火墙
一.centos关闭防火墙 1,关闭防火墙.service iptables stop 2,关闭防火墙开机自启.chkconfig iptables off 3,查看防火墙状态.service ipt ...
- go源码分析(三) 使用go http包开发web时遇到的坑之卸载插件,重启插件管理,仍然可以访问已经卸载的插件
问题描述: web页面下发重启指令后,对卸载插件的处理不完整(虽然列表已经没有插件描述,但是在HandleFunc的路由列表中依然存在) 我们需要清空路由列表map 路由列表结构见代码: net/ht ...
- HDU 5448 Marisa’s Cake
给定一个由n个整点构成的凸多边形,求从n个点里任意选不少于3个点组成的所有凸多边形的面积之和,显然整点构成的多边形面积一定是0.5的整数倍,所以题目需要你算出答案的2倍 mod1000000007的值 ...
- Openstack计算Nova组件
欢迎来到虚拟机的世界,如果我们将Openstack环境里运行在各个无力节点上的各种服务看座生命体,而不是死的指令集合,那么就是一个虚拟机的世界. Openstack的计算组件,也就是Nova项目实现了 ...
- How to do error checking in CUDA(如何在CUDA里做错误检查)
https://codeyarns.com/2011/03/02/how-to-do-error-checking-in-cuda/ Error checks in CUDA code can hel ...
- Linux 应用领域
与Windows操作系统软件一样,Linux也是一个操作系统软件.但与Windows不同的是,Linux是一套开放源代码程序的,并可以自由传播的类UNIX操作系统软件,随着信息技术的更新变化,Linu ...
- 原创】Java并发编程系列2:线程概念与基础操作
[原创]Java并发编程系列2:线程概念与基础操作 伟大的理想只有经过忘我的斗争和牺牲才能胜利实现. 本篇为[Dali王的技术博客]Java并发编程系列第二篇,讲讲有关线程的那些事儿.主要内容是如下这 ...