|

Aimee

Write the Code. Change the World.

从输入url到页面展示

· 分享镜#h5

1.输入url并回车确认

2.url解析/dns解析

浏览器进程会通过进程间通信(IPC)把URL请求发送至网络进程,网络进程接收到URL请求后,会在这里发起真正的URL请求流程。

2.1 网路进程会查找本地缓存是否缓存了该资源

  • 有缓存资源,直接返回资源给浏览器进程
  • 缓存中没有查找到资源,直接进入网络请求流程
  • 缓存的查找
    • 先查找内存,如果内存中存在,从内存中加载(from memory cache)
    • 如果内存中未找到,选择硬盘获取,如果硬盘中存在,从硬盘中加载(from disk cache)
    • 如果硬盘中未找到,那就进行网络请求

2.2 DNS解析

目的:

  • 获取请求域名的服务器IP地址

过程:

  • 在浏览器DNS缓存中搜索
  • 如果浏览器缓存中没有,操作系统会先检测自己本地的hosts文件是否有这个网址映射关系,如果有,直接返回,完成域名解析。
  • 如果本地hosts中没有映射关系,则会找本地DNS服务器,如果要查询的域名包含本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性
  • 如果要查询的域名,不由本地DNS服务器进行迭代查询,但该服务器已缓存了此网站映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性
  • 如果上述方法都失效,由本地DNS服务器进行迭代查询,先向根域名DNS服务器发出请求,再查二级域,三级域,直到查询到要解析的地址或名字为止,本地DNS服务器收到应答后,先在缓存中存储,然后将解析结果返回客户机

扩展:

  • 所有DNS请求和回答报文使用的UDP数据报经过端口53发送经过若干ms到若干s的延时后,用户主机上的DNS客户端接收到一个提供所希望映射的DNS回答报文。
  • DNS不采用单点的集中式的设计方式,而是使用分布式集群的工作方式,是因为集中式设计或有单点故障、通信容量、远距离时间延迟、维护开销大。

2.3 利用IP地址和服务器建立TCP链接

  • 三次握手

2.4 发送请求

  • 浏览器端会构建请求行、请求头等信息,并把和该域名相关的Cookie等数据附加到请求头中,然后向服务器发送构建的请求信息

2.5 服务器接收到请求信息后,会根据请求信息生成响应数据,并发给网络进程

2.6 网络进程接收了响应内容后开始进行解析

  • 重定向
    • 通过状态码判断301或302
    • 获取location字段里面的值重新发起请求
  • 响应数据类型处理
    • 通过Content-Type字段判断
    • 若为text/html类型,浏览器会继续进行导航流程
    • 若为下载类型,如application/octet-stream, 请求会被交给浏览器的下载管理器,同时该URL请求的导航流程就此结束

3.准备渲染进程

两种情况:

  • 通常情况下,打开新的页面会使用单独的渲染进程
  • 如果从A页面打开B页面,且A和B都属于同一站点的话,B页面复用A页面的渲染进程

同一站点:

  • 定义为根域名和协议一样

注意:

  • 渲染进程准备好了之后,还不能立即进入文档解析状态,因为此时的文档数据还在网络进程中,并没有提交给渲染进程,所以下一步就进入了提交文档阶段。

提交文档:

  • 提交文档的消息是有浏览器进程发出的,渲染进程收到提交文档的消息后,会和网络进程简历传输数据的管道
  • 等文档数据传输完成之后,渲染进程会返回确认提交的消息给浏览器进程
  • 浏览器进程在收到确认提交的消息后,会更新浏览器界面状态,包括了安全状态,地址栏的URL、前进后退的历史状态,并更新Web页面

4.渲染阶段

4.1 构建DOM树

目的:

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

输入内容:

  • HTML文件

处理过程:

  • 经由HTML解析器解析

输出内容

  • 输出树状结构的DOM

4.2 样式计算

目的:

  • 为了计算出DOM节点中每个元素的具体样式

输入内容:

  • 通过link引用的外部CSS文件
  • 元素的style属性内嵌的CSS

处理过程:

  • 把CSS转换为浏览器能够理解的结构——styleSheets, 该结构同时具备了查询和修改功能
  • 转换样式表中的属性值,使其标准化
  • 计算出DOM树中每个节点的具体样式
    • CSS的继承规则
      • 每个DOM节点都包含有父节点的样式,会根据DOM节点的继承关系来合理计算节点样式
    • 层叠规则
      • 层叠是CSS的一个基本特征,是一个定义了如何合并来自多个源的属性算法
  • 输出内容
    • 每个DOM节点的样式,并被保存在CompytedStyle的结构内

4.3 布局阶段

目的:

  • 计算出DOM树中可见元素的几何位置,把这个计算过程叫做布局

输入内容:

  • DOM树 + ComputedStyle

处理过程:

  • 创建布局树
    • 构建一颗质保函可见元素布局树
    • 遍历DOM树中的所有可见节点,并把这些节点加到布局中;不可见的节点会被布局树忽略掉,如head标签下面的全部内容
  • 布局计算
    • 计算布局树节点的坐标位置

输出内容:

  • 布局树

4.4 分层

目的:

  • 渲染引擎需要为特定的节点生成专用的图层,并生成一颗对应的图层树(LayerTree)

输入内容:

  • 布局树

处理过程:

  • 何时会被分层(拥有其中一个点就被提升为单独的一个图层)
    • 拥有层叠上下文属性的元素会被提升为单独的一层
    • 需要裁剪clip的地方会被创建为图层(当超出容器内容被隐藏或者出现滚动条均会被提升为单独层)

输出内容:

  • 图层树(LayerTree)

4.5 图层绘制

目的:

  • 渲染引擎会对图层树中的每个图层进行绘制

输入内容:

  • 图层树

处理过程:

  • 渲染引擎会把一个图层的绘制拆分成很多小的绘制指令,然后把这些指令按照顺序组成一个待绘制列表

输出内容:

  • 待绘制列表
  • 绘制列表只是用来记录绘制顺序和绘制指令的列表,而实际上绘制操作是由渲染引擎中的合成线程来完成的

当图层的绘制列表准备好了之后,主线程会把该绘制列表提交给合成线程 ​

4.6 分块

  • 扩展
    • 视口
      • 通常一个页面可能很大,但是用户只能看见其中的一部分,把用户可以看到的这个部分叫做视口(viewport)
  • 若页面很大,但是通过视口用户只能看到很小一部分,为了提示性能,合成线程会将图层划分为图块(tile),图块大小通常是256256 或512512

4.7 栅格化操作

  • 合成线程会按照视口附近的图块来有限生成位图,实际生成位图的操作时由栅格化来执行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的
  • 栅格化过程都会使用GPU加速生成,使用GPU生成位图的过程叫快速栅格化,或者GPU删格化,生成的位图保存在GPU内存中。
    • 渲染进程把生成图块的执行发送给GPU,然后再GPU中执行生成图块的位图,并保存在GPU的内存中

4.8 合成和显示

  • 一旦所有图块都被光栅化,合成线程就会生成一个绘制图块的命令——DrawQuad, 然后将该命令提交给浏览器进程
  • 浏览器进程里面有一个叫viz的组件,用来接受合成线程发过来的DrawQuad命令,然后根据DrawQuad命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。

5.js解析

整体的步骤分为:

  • 词法分析
  • 语法分析,转换成ast
  • 生成该代码片段的执行上下文
  • 解释器根据AST生成字节码
  • 进入执行阶段
  • 如果频繁执行的代码会被转成机器码

创建window对象

  • window对象也叫全局执行环境,当页面产生时就被创建。
  • 所有的全局变量和函数都数据window的属性和方法,而DOM Tree也会映射在window的document对象上。
  • 当页面销毁时,全局执行环境会被销毁。

加载文件

  • 完成js引擎分析它的语法和词法是否合法,如果合法进入预编译

预编译

  • 生成变量对象
    • 在预编译的过程中,浏览器会寻找全局变量声明,把它当作window的属性加入到window对象中,并给变量赋值undefined
    • 寻找全局函数声明,把它当作window的方法加入到window对象中,并将函数体赋值给他(匿名函数不参与预编译的,因为它是变量)
    • 变量提升,包括函数提升
  • 建立作用域链
  • 确定this指向

解释执行

  • 变量赋值
    • 执行到变量就赋值,如果变量没有被定义,也没有被预编译直接复制,在es5非严格模式下就会称为window的一个属性,也就是全局变量。
    • string/number、boolean这样的值就直接把值放在变量的存储空间里,object对象就是把指针指向变量的存储空间
  • 函数引用
  • 执行其他代码
  • 函数的执行
    • 将函数的环境推入一个环境的栈中,执行完成后再弹出,控制权交还给之前的环境。

垃圾回收

  • 当函数执行完毕之后,会从调用栈中弹出、销毁、等待浏览器的垃圾回收。

结论

  • js执行是单线程的
  • 只有栈顶的上下文处于执行中,其他上下文需要等待
  • 全局上下文只有一个
  • 函数执行上下文的个数没有限制
  • 某个函数被调用,就会有新的执行上下文被创建,调用自身也是如此
  • 当分配的调用栈空间被占满时,会引发“堆栈溢出”问题

评论7

登录后参与评论。

  • 游客

    棒棒

  • 游客

    666

  • 游客

    你好

  • 游客

    你好

  • 游客

    你好

  • 游客

    你好

  • 游客

    https://mangoya.cn/img/xixi.913e2f3d.gif挖鼻

回到顶部