前端,从输入URL到用户看到页面,简述

参考优质博文:从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!

浏览器分配一个进程(浏览器渲染线程)给这个页面

页面是多线程的:

  • http请求会被分配一个异步http请求线程,
  • 页面渲染分配一个GUI渲染线程,
  • JS代码涉及到JS引擎线程、事件触发线程、计时器触发器线程
    • 代码中的setTimeout和setInterval等计时器,会放入计时器触发器线程,到时间了回调函数就被推入执行事件队列
    • 事件触发线程是浏览器给JS引擎线程开的外挂,用来控制事件循环的。
    • JS引擎线程用于执行JS代码,从事件队列中取事件执行,JS引擎线程和GUI渲染线程是互斥的,所以JS代码如果太拉了,就会影响页面渲染。

强缓存判断,如果缓存失效了的话,进行下面的

URL解析:

  • 如果host不是ip地址,就拿着host去DNS域名服务器进行查询,中间可能经过路由、缓存
  • 拿到了ip地址,准备握手建立连接。

三次握手建立TCP连接

  • 客户端:外,哥们,开个门,听到了没,听到了吱一声。(试图确认服务端的正常收发能力)
  • 服务端:听到了,超,我听到了,你听到我了吗。(确认了客户端的正常发送能力,试图确认客户端的正常接收能力)
  • 客户端:听到了,ok,可以建立连接了。(客户端确认了服务端的正常收发能力)
  • 服务端收到最后一次招呼,确认了客户端的正常接收能力,连接建立。

https的话再进行 SSL/TLS 握手

  • 客户端:生成一个随机数,将随机数A和一系列加密算法发送给服务端
  • 服务端:收到,存下A,挑选一组加密算法Z和hash算法,生成一个随机数B,将随机数B和加密算法Z发送给客户端。然后,自己的网址+自己的公钥+证书颁发机构的信息打包 = 证书,发送给客户端。一共两个包,两次发送
  • 客户端:收到,验证证书是否值得信任,完事儿拿到服务端的公钥,存下随机数B,自己生成一个随机数C,用服务端公钥和加密算法Z加密C。用A+B+C按照一定方式生成对称密钥X,使用X加密一段明文信息得到密文,然后用约定方式hash明文信息,得到hash段,加密了的C+密文+hash段打包发送给服务端
  • 服务端:收到,用私钥和加密算法Z解密得到C,用相同的一定方式将A+B+C生成对称密钥X,用X解密密文得到明文信息,用约定的hash算法hash同一段明文信息得到服务端hash段,同客户端发来的hash段进行比较,一致则说明ok。然后使用X加密一段明文得到密文,并hash这段明文,hash段和密文一同发送给客户端
  • 客户端:收到,用X解密密文得到明文,明文进行hash,和服务端发来的hash端进行比较,一致则说明可以建立加密通道。使用X进行对称加密通话。

发出正式的 http 请求

  • tcp连接建立了就可以正式发送请求了。
  • get请求就只发送一个包,post的话先发送请求头header,得到status=100后,再发送body请求体(火狐浏览器的话post也是只发一个包),返回status=200的话,ok。

协商缓存判断,如果缓存失效了的话,进行下面的

  • 如果上面返回的只是一个返回头,然后返回头的E-tag和浏览器请求头的If-None-Match匹配,说明304,使用本地的协商缓存,http1.1。如果是http1.0,则是服务端Last-Modified和客户端If-Modified-Since两个头字段进行匹配。

后台交互,把资源发给前端

  • 后端的,不去了解。

前端拿到返回资源,解析

  • 解析HTML,构建DOM树,bytes-characters-tokens-nodes-DOM
    • 转换:bytes->字符
    • 分词:字符->词元(有了自己的含义)
    • 词法分析:词元->对象(有了自己的属性和规则)
    • DOM构建:对象->树形结构(对象之间有了关系)
  • 解析CSS,构建CSS规则树,bytes-characters-tokens-nodes-CSSOM
  • 合成DOM树和CSS规则树,生成render树
    • 将两棵树合成,样式和DOM元素合成,一些不可见的元素(存在于DOM树中的)就不会进入渲染树
  • 布局render树,引起回流(reflow|重排),元素的尺寸、位置计算(这中间可能就有一些JS代码影响了渲染树,导致了回流和重绘)(用本地缓存存储一些访问时会导致回流的变量,可以降低回流的频率)
  • 绘制render树(paint),绘制页面像素信息
  • 浏览器将各层信息发送给GPU,GPU将各层合成(composite),显示在屏幕上
  • 单独的,外链资源的加载:
    • img资源,异步下载,不会阻塞各种解析,下载完就直接替换原有src的位置
    • css资源,不会阻塞HTML的解析,但是会阻塞渲染树的构建(media query声明的css资源不会阻塞)
    • js资源,会阻塞HTML的解析,下载完并执行后才会继续HTML的解析。
      • 如果加了defer,下载完之后等待到html解析完了才会执行,是延迟执行;如果加了async,下载完就立即执行,没有先后顺序,谁先下载完谁先执行,所以可能造成js之间的阻塞,是异步下载。
      • 有的浏览器也有优化,可以并发下载,但也只是优化下载过程,解析和执行过程的阻塞还是管不着的。
  • JS引擎解析(单独拿出来讲):
    • 解释阶段
      • 词法分析,代码->词元
      • 语法分析,词元->语法树
      • 使用翻译器将代码转换成字节码(bytecode),谷歌的V8引擎会直接把代码转换成机器码。
      • 使用字节码解释器将字节码转换成机器码
    • 预处理阶段,为了确保JS代码正确执行
      • 变量提升
      • 分号补全等
    • 执行阶段
      • 执行上下文,下面三个都是执行上下文的三个属性;执行堆栈。
        • 执行上下文都存在一个栈中
          • 浏览器组开始执行JS,创建一个全局执行上下文,压入执行栈
          • 然后每进入一个作用域,就创建对应的执行上下文压入栈顶
          • 每从一个作用域退出,就把栈顶的执行上下文弹出来,将上下文控制权交给栈顶元素
          • 最后都会回到全局执行上下文。
      • VO和AO,对象变量和活动变量:函数中AO === VO,全局中AO === this === global
        • 对象变量和当前执行上下文有关。
        • 活动变量是函数被调用者激活之后出现的。
      • 作用域链,类似于原型链,变量的寻找是从内向外的,一层一层,最外面都找不到那就报错
      • this,this引出的变量,本层找不到的话不会沿着作用域链找,之和当前上下文有关。
    • 回收机制(我看看书再补充)
      • 标记清除
      • 引用计数
        • 被引用时加一
        • 被减持时减一
        • 清除引用数为0的变量

用户看到页面

おすすめ

転載: blog.csdn.net/weixin_45543674/article/details/121892580