输入url到页面显示发生了什么?

前沿:浏览器的多进程架构

chrome的多进程架构主要包括以下几个进程:

  • 1、浏览器(主)进程:主要负责子进程管理、页面显示(地址栏、工具栏、书签栏等UI元素)、用户交互(处理用户的输入,如点击、滚动、键盘输入等)、数据存储等功能。
  • 2、渲染进程:核心是解析和运行html、css、js,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中。默认情况下每个tab标签都有一个独立的渲染进程,但是如果从一个页面打开了一个新页面,而新页面和原页面属于同一站点(协议与根域名相同),那么新页面就会和原页面共用一个渲染进程。
  • 3、网络进程:用于处理网络请求,负责与服务器的通信。
  • 4、插件进程:负责插件的运行。
  • 5、GPU进程:负责处理整个应用程序的GPU任务。
    进程之间通过IPC机制进行通信。
输入url到页面显示的流程

整个过程需要各个进程之间的配合

  1. 用户输入:
    浏览器进程接收用户输入,检查url与组装协议,构成完成的url(如果是搜索内容,浏览器默认搜索引擎+搜索关键字,组成新的url;如果输入的内容符合url规则,如输入的baidu.com,会加上协议https,组成完整的urlhttps://baidu.com),通过IPC(进程通信机制)将完整url转发给网络进程
  2. url请求:
    网络进程接收到url请求的流程:
    2.1. 首先查找是否已缓存资源,有缓存,直接返回资源给浏览器进程,无缓存发起网络请求,进入到下一步
    2.2. DNS解析:获取url对应的ip地址
    2.3. 利用IP地址和服务器建立TCP连接(三次握手),如果是https请求还需要建立TLS连接
    2.4. 连接建立后,向服务器发送HTTP请求,请求包括请求行(GET 或POST),请求头(User-Agent、Accept、Cookie等信息),请求正文等内容。
    2.5. 服务端处理请求生成相应数据(包括响应行、响应头、响应体),并发给网络进程。
    2.6. 网络进程接收响应数据。如果返回响应行中的状态码是301/302,说明服务器需要浏览器重定向到其他url,这时网络进程会从响应头中读取Location字段的值也就是重定向的地址,然后发起新的http/https请求(回到2.1)
    2.7. 状态码200,检查content-type,如果是字节流类型,会将该请求提交到下载管理器,是html,则通知浏览器进程准备渲染进程
  3. 准备渲染进程
    浏览器进程检查是否需要重开渲染进程,如果有符合复用要求的(旧页面中打开的且属于同一站点)复用原来的进程,如果不同,则开启新的单独的渲染进程
  4. 渲染
    4.1. 渲染进程准备好后,浏览器进程向渲染进程发起“提交文档”的消息,渲染进程接收到消息和网络进程建立传输数据的“管道”
    4.2. 渲染进程接收完数据后,向浏览器发送“确认提交” ,浏览器进程接收到确认消息后更新浏览器界面状态:安全、地址栏url、前进后退的历史状态等。
    4.3. 渲染进程对文档进行页面解析和资源加载:
    • 构建DOM树:渲染进程将html转换为dom树结构
    • 样式计算生成styleSheets
    • 根据dom树和styleSheets生成布局树(不包括隐藏的DOM元素,如display:none的元素、和head元素)
    • 对布局树进行分层,并生成分层树(layerTree)
    • 渲染引擎将每个图层的绘制拆分成很多小的绘制指令,然后将指令按照顺序组成一个待绘制列表,并提交到渲染进程中的合成线程
    • 合成线程将图层划分为图块(tile),然后将图块转换为位图(栅格化),通常栅格化过程都会使用 GPU 来加速生成。所有的图块都被栅格化后,合成线程会生成一个绘制图块的命令“ DrawQuad”,将该命令提交给浏览器进程
    • 浏览器进程接收到合成线程发过来的命令,根据命令将页面内容绘制到内存中,再将内存显示在屏幕上


      渲染流程示意图
重排(reflow)和重绘(repaint)
  • 重排(Reflow):会触发重新布局


    重排.png
  • 重绘(Repaint):没有引起几何位置的变换,没有执行布局阶段,直接进入了绘制阶段,然后执行之后的一系列子阶段。重绘并不会造成额外的计算或布局,所以性能影响较小。


    重绘.png

减少重排重绘,相当于减少了渲染进程的主线程和非主线程的很多计算和操作,能够加快web的展示。

  • 1、使用 class 操作样式,而不是频繁操作 style(触发repaint/reflow的操作尽量放在一起): 如通过使用 class 来集中修改样式,而不是通过 style 一个一个的修改
  • 2、 批量dom 操作:如通过虚拟dom计算出操作总得差异,一起提交给浏览器。
  • 3、 避免使用 table 布局: 由于浏览器使用流式布局,对 Render Tree 的计算通常只需要遍历一次就可以完成,但 Table 及内部元素除外,通常需要多次计算且需花费3倍同等元素时间。其次,很小的改动可能会导致整个 table 都重新布局
  • 4、 Debounce window resize 事件: 防抖可以防止频繁触发重排重绘,例如 window resize 可以设置为 1s 内只可以触发一次
  • 5、 dom读写操作分离:
    浏览器的渲染队列机制:当我们修改了元素的几何属性,导致浏览器触发重排或重绘时。它会把该操作放进渲染队列,等到队列中的操作到了一定的数量或者到了一定的时间间隔时,浏览器就会批量执行这些操作
div.style.left = '10px';
div.style.top = '10px';
div.style.width = '20px';
div.style.height = '20px';

上述操作会上次回触发一次重排+重绘

div.style.left = '10px';
console.log(div.offsetLeft);
div.style.top = '10px';
console.log(div.offsetTop);
div.style.width = '20px';
console.log(div.offsetWidth);
div.style.height = '20px';
console.log(div.offsetHeight);

上述操作会上次回触发四次重排+重绘
当我们同时进行DOM属性的读写操作的时候,浏览器在读取属性值之前,需要将之前队列中的所有写操作执行一遍。比如,我们连续写入两次样式,浏览器会合并这两次写操作;但是如果我们在两次写操作中加入一次读操作,那么浏览器就不能合并这两次写操作了,从而产生两次重绘和重排,导致性能的消耗。
因此,将读写操作分离,也就是尽量合并读操作和写操作,避免互相混杂,可以减少浏览器的渲染次数,从而提高性能

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容