一文摸透从输入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等文件,经过浏览器就会显示出漂亮的页面了。

作者:AhuntSun
链接:https://juejin.im/post/5e8be3f2f265da47d12914fc
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

url上接收到 el表达式 不渲染_一文摸透从输入URL到页面渲染的过程相关推荐

  1. jquery 当页面图片加载之后_在浏览器地址栏输入地址到页面渲染完成发生了什么?(下)...

    上一篇讲了前三步,本篇从第四步开始.下面是正文: 四.进行tcp三次握手,建立tcp连接. 简述一下,第三步我们找到了目标ip,并获得了服务器ip的mac地址.此时浏览器就会请求和服务器连接,用来传输 ...

  2. 后端数据成功返回 页面不渲染_在浏览器地址栏输入地址到页面渲染完成发生了什么?(下)...

    上一篇讲了前三步,本篇从第四步开始.下面是正文: 四.进行tcp三次握手,建立tcp连接. 简述一下,第三步我们找到了目标ip,并获得了服务器ip的mac地址.此时浏览器就会请求和服务器连接,用来传输 ...

  3. html将页面分成三块_导航渲染流程你真的知道从输入URL到页面展示发生了什么吗?(内附思维导图)...

    导航渲染流程 通过这篇文章当你被问到从URL输入到页面展示都发生了什么的时候,基本都能对答如流,甚至可以一直深入的说,说到面试官闭麦哈哈哈~ 以下是本文的思维导图,直接拿图「点个赞」再走吧 ~ 求求了 ...

  4. java el表达式 导航规则_诺禾:在jsp里面如何不写java代码展示数据(EL表达式的使用)...

    EL表达式可以简化jsp中写的java代码 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码展示数据(EL表达式的使用) 在jsp里面如何不写java代码 ...

  5. 赋值后页面不渲染_第七节:框架搭建之页面静态化的剖析

    一. 前言 抛砖引玉: 提到项目性能优化,大部分人第一时间就会想到缓存,针对"读多写少"的数据,可以放到缓存里,设置个过期时间,这样就不用每次都去数据库中查询了, 减轻了数据库的压 ...

  6. el表达式的语法_「手把手教python3接口自动化」「第三章」:Python3 语法

    1 Python3 语法 1.1 基础语法 [编码] 默认情况下,Python 3 源码文件以 UTF-8 编码,所有字符串都是 unicode 字符串. 当然你也可以为源码文件指定不同的编码. [标 ...

  7. vue 大数据 渲染_技术专栏 | DMap——实战Vue百万条数据渲染表格组件开发

    作者:TalkingData 李志刚 本文由TalkingData原创,转载请获取授权. 李志刚:近几个月在开发一个基于Vue的数据可视化分析辅助应用---DMap(谛听),一套为数据分析师和数据科学 ...

  8. ae怎么设置gpu渲染_有玩AE的吗?求教GPU渲染问题!!

    iMac2013 3.1GHz 四核 Intel Core i7,Turbo Boost 高达 3.9GHz 8GB 1600MHz DDR3 SDRAM - 2X4GB 1TB Serial ATA ...

  9. 从文档流角度理解浏览器页面渲染引擎对元素定位的解析

    文档流:将窗体自上而下分成一行一行,并在每行中按从左至右的挨次排放元素,即为文档流. 我们在排列元素时,遵循"流式结构",即元素遵循从上向下,从左向右堆叠的规则,所以我们在排列元素 ...

最新文章

  1. centos修改oracle字符集
  2. jsp上传下载+SmartUpload插件上传
  3. android surface windows,【技术攻略】s3 硬盘android+windows10双系统
  4. php socket开发斗地主,基于状态机模型的斗地主游戏(NodeJsSocketIO)
  5. Java8————日期时间 API
  6. Python笔记-使用SSIM找两张图不同及使用Opencv显示
  7. OS开发之Objective-C与JavaScript的交互
  8. 在C#中使用DevExpress中的ChartControl实现极坐标图
  9. DoIP(二)——报文类型
  10. SAP - MM - 第3篇 - 供应商主数据
  11. 高效工作-使用石墨文档进行信息收集
  12. 【yolo训练数据集】标注好的垃圾分类数据集共享
  13. 中英文双标题latex
  14. 二线城市疯狂抢人,技术人才何去何从?
  15. 《克隆人的进攻》面向对象Java版
  16. codeforce 141A
  17. matlab 数组索引必须为正整数或逻辑值
  18. Spark的现状与未来发展
  19. 让阿根廷队“告吹”的三个球背后,2022 年世界杯暗藏哪些技术玄机?
  20. 【附源码】计算机毕业设计JAVA茶店订购管理系统

热门文章

  1. 一台计算机连入计算机网络后通过该计算机,一台计算机连入计算机网络后,该计算机( )。...
  2. java fx dialog_JavaFX 如何使用內建的對話框(Dialog)?
  3. linux ejb远程调用,[转载]在容器外使用EJB 3.0 Persistence
  4. mac mysql 设置短命令_短小强大的8个命令,分分钟帮你提高工作效率!
  5. php中module,module.php
  6. java判断实例_java判断类和实例的关系
  7. springboot 打印乱码_Springboot中使用logback输出日志中文乱码
  8. nfvo通过调用哪个接口实现对vnf生命周期的管理_Spring-Bean生命周期
  9. 信息竞赛进阶指南--单调栈(模板)
  10. 图论--双连通分量--点双连通模板