宏观视角下的浏览器:地址栏键入URL后会发生什么?HTML,CSS,JS又是怎么变成页面显示出来的

103 阅读5分钟

浏览器原理与实践系列文章内容来自极客时间李兵老师《浏览器工作原理与实践》,主要是记录自己的学习过程,基于自己的理解对内容做的一些总结,包括《宏观视角下的浏览器:地址栏键入URL后会发生什么?HTML,CSS,JS又是怎么变成页面显示出来的》《JS中内存机制、数据类型、V8引擎垃圾回收原理、V8怎样执行JS代码,据此可以做哪些性能优化》《V8引擎工作原理》《事件循环系统:宏任务微任务如何有条不紊的执行?》《浏览器中的页面:重绘重排及合成?如何提高页面渲染性能》《网络协议:http1、http2、http3都有些什么优缺点?》《浏览器安全:xss及CSRF攻击有何特点?如何防御》共七篇,此为第一篇

浏览器架构

线程:操作系统能够进行运算调度的最小单位。

进程:一个进程就是一个程序的运行实例。启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,把这样的一个运行环境叫进程。

线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

进程和线程之间的关系4个特点。

  1. 进程中任意线程执行出错,都会导致整个进程崩溃
  2. 线程之间共享进程中的数据
  3. 当一个进程关闭后,操作系统会回收进程占用的内存
  4. 进程之间内容相互隔离(通过IPC机制进行通信)

现代浏览器为多进程架构,打开一个页面,浏览器至少会打开四个进程 -- 浏览器主进程、渲染进程、GPU进程、网络进程。

  • 浏览器进程:主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
  • 渲染进程:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎Blink和JavaScript引擎V8都是运行在该进程中,默认情况下,Chrome会为每个Tab标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
  • GPU进程:实现3D CSS效果,UI界面绘制。
  • 网络进程。主要负责页面的网络资源加载。
  • 插件进程。主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。

地址栏键入URL后会发生什么?

image.png

  1. 构建请求:浏览器准备发起网络请求,构建请求行等
  2. 查找缓存:若命中强缓存,直接拦截请求,从本地获取资源
  3. 准备IP地址和端口:DNS查询获取IP,端口号一般默认80
  4. 等待TCP队列:http1.1,浏览器请求限制一般为一个域名最多维持6个请求连接,如果发送网络请求超过6个,则会进入等待对列排队
  5. 建立TCP连接:3次握手
  6. 发起HTTP请求:浏览器会向服务器发送请求行,包括了请求方法、请求URI和HTTP版本协议。
  7. 服务器处理并响应请求:成功返回状态码200,304命中缓存,301/302重定向
  8. 断开TCP连接:4次挥手

渲染流程:HTML、CSS和JavaScript,是如何变成页面的?

  1. 构建DOM树:浏览器无法直接理解和使用HTML,所以需要将HTML转换为浏览器能够理解的结构——DOM树

  2. 样式计算:

    1. 把CSS转换为浏览器能够理解的结构 -- styleSheets
    2. 转换样式表中的属性值,使其标准化,比如将颜色‘red’转化成渲染引擎可以理解的rgb值
    3. 计算DOM中每个节点的具体样式,涉及到CSS的继承规则和层叠规则
  3. 布局阶段:有了DOM树和样式,还不足以显示页面,接下来就需要计算出DOM树中可见元素的几何位置,这个计算过程叫做布局。

    1. 创建布局树:构建一颗元素布局树,比如去掉head等没有实际元素的标签,去掉display为none的元素等
    2. 布局计算:
  4. 分层:页面中有很多复杂的效果,如一些复杂的3D变换、页面滚动,或者使用z-indexing做z轴排序等,为了更加方便地实现这些效果,渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树。所以浏览器的页面实际上被分成了很多图层,这些图层叠加后合成了最终的页面

  5. 图层绘制:渲染引擎将每个图层的绘制拆分成很小的绘制指令,再将指令按顺序组成待绘制列表,最后根据该列表绘制图层。

  6. 栅格化操作:通常一个页面可能很大,但是用户只能看到其中的一部分,这个部分叫做视口。在有些情况下,有的图层可以很大,比如有的页面要滚动好久才能滚动到底部,但是通过视口,用户只能看到页面的很小一部分,所以在这种情况下,要绘制出所有图层内容的话,就会产生太大的开销,而且也没有必要。基于这个原因,合成线程会将图层划分为图块,这些图块的大小通常是256x256或者512x512。然后合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化执行的最小单位。

  7. 合成和显示:所有图块都栅格化完成后,合成线程将指令提交给浏览器进程,浏览器进程根据指令将页面内容绘制到内存中,最后从内存中取出图像显示到屏幕上。