主要构成部分

  • 用户界面
  • 浏览器引擎(WebCore)负责窗口管理、Tab进程管理
  • 渲染引擎,也叫内核,负责html解析、页面渲染
  • Js引擎,JsCore,js的解释执行

浏览器

  • 多进程有四种:渲染进程、插件进程、GPU进程、浏览器进程

  • 多线程(js引擎才是单线程),主要看渲染进程,它包括

    • GUI线程,负责解析html、css和渲染页面 相关的
    • JS引擎线程,负责js的解释执行(统一时期只能有一个此类线程执行)
    • 事件线程,控制事件循环相关逻辑(定时器和异步请求的回调)
    • 定时器线程,处理定时器相关逻辑
    • 异步请求线程,发起Ajax时会生成该线程

    注意:GUI线程和Js引擎线程是互斥的,即当GUI线程执行时,js引擎会停下,反之亦然。

    这里说一下自我理解的js为什么设计为单线程吧,首先js是一门脚本语言,它只是需要在浏览器中运行,所以应该尽可能的简单,抛弃了一些多线程操作(这样就可以减少因为操作同一资源而使用锁,等复杂情况)设计成了单线程。同时因为是单线程且js是面向用户的,用户使用体验提高是刚需,所以js又需要是异步的,不用阻塞等待。

    总的来说就是:简单的脚本——》单线程——》异步;

    应该也是这个原因——不能同时操作一个资源,DOM要么被GUI线程操作(计算布局)要么被js操作(增删改DOM),所以才有上面的注意,js和GUI线程在同一时刻只能执行一个。

页面渲染

  • 解析html生成Dom树(中间遇到js,停下,执行js)
  • 解析css生成css对象模型树(CSSOM)
  • 合并DOM和CSSOM生成渲染树(render树)
  • 根据渲染树进行计算布局(layout)然后绘制(painting)得到页面

在应用被使用的过程中可能会产生一些增减DOM节点的操作,由上面过程可以知道,DOM树会被改变,这时就需要重新构建渲染树,再进行渲染,而这过程称重排或者回流(reflowing);倘若DOM节点改变的只是一些字体背景颜色,不影响布局,不需要重新计算时,只需要重新绘制,这个操作称重绘。

重排则必定包含重绘;当改变的无关布局的(字体颜色等),则会触发重绘而不必重排

浏览器缓存

  • 由浏览器实现的http缓存:

    • 强缓存
    • 协商缓存

    强缓存:其实就一种比较强制性的匹配缓存规则而已

    • 概述:总的的来说就是,服务端第一次响应客户端发送的请求时给予客户端一个时间,表明这些数据在这个时间内一定不会改变数据(改变也可以,但客户端不需要知道),可以直接读缓存,不用再次发送http请求
    • 具体使用:
      • http1.0时使用的字段Express,它的值是一个绝对时间,如 Wed, 21 Oct 2020 07:28:00 GMT。第一次时,http响应头带着这个字段,浏览器就会缓存下这些数据,并且在应用在这个时间,2020.10.21 07:28:00 前,再次请求这个url时读缓存中的这些数据返回,不发送http请求
      • http1.1时使用的字段是Cache-Control,它的值是一个相对的时间,如max-age=3600。第一次请求时,http响应头带着这个字段,浏览器会缓存下这些数据,并且在应用在过了这个相对时间,3600秒前,再次请求这个url时读缓存中的这些数据返回,不发送http请求
    • http1.1的记录的相对时间会比绝对时间好一点,因为客户端的时间(用户的电脑)可以是不准确的,如果偏后,那么浏览器就可能读不到缓存直接再次请求数据,缓存就失效了。使用相对时间,无论如何,距离上次请求的一段时间都读缓存,客户端时间无法再干扰到了。

    协商缓存:另一种的匹配缓存规则

    • 概述:相对强缓存由浏览器判断是否读缓冲,协商缓存把这个判断放到了服务端,即客户端请求会到达服务端,这个是和强缓存最大的区别。客户端请求时,服务端会返回一个标记,客户端再次请求时,请求头应该带上这个标记,服务端根据这个标记判断客户端上次请求的数据是否还能用,能用就返回一个http状态码,让浏览器读缓存里的数据,不能用就返回能用的数据。

    • 具体使用:

      • 使用Last-Modified/If-Modified-Since这一对字段。第一次响应时,服务端在响应头里增加Last-Modified字段,值是时间,表示数据最新的更改时间;下一次再请求相同的数据,浏览器会在请求头里增加字段If-Modified-Since,值就是Last-Modified的时间,请求到达服务端后,服务端就读到If-Modified-Since这个字段的时间比对数据更新的最新时间,相同就返回304,让浏览器读缓存里的数据,不然就返回最新的数据。
    • 使用

      ETag/If-None-Match这一对字段。

      ETag的值是一段内容摘要(hash)。类似的,第一次响应的响应头部也会带上一个ETag字段,下次请求在请求头部加If-None-Match带上这个Etag的值,服务端拿着和现在的数据摘要对比,相同则返回304,不同则返回最新数据;

      • ETag/If-None-Match相比Last-Modified/If-Modified-Since是一种更强的校验器,Last-Modified的时间只能精确到秒。同时ETag/If-None-Match也比Last-Modified/If-Modified-Since优先级更高。
  • 随记:

    • 这些缓存都是针对get,head这些读数据的方法而言,那些字段也有自身的一些其它用法

参考:

HTTP 缓存

Expires

Cache-Control
ETag

If-None-Match

If-Match

Prevent unnecessary network requests with the HTTP Cache

(1.6w字)浏览器灵魂之问,请问你能接得住几个?

最后更新: 2021年07月15日 23:43

原始链接: https://idkhts.github.io/2021/01/19/%E6%B5%8F%E8%A7%88%E5%99%A8/