【知识梳理】4.浏览器_4.20

232 阅读8分钟

注:以下内容为随手记,属于暂未成形的文章,请勿参考

浏览器组成

多进程架构

v2-c203599b09f98981ef4cb79ad23c97db_r.jpg

  • 浏览器主进程:界面显示、用户交互、进程管理、存储功能

  • 渲染进程:渲染执行HTML、CSS和JS。

默认情况下,Chrome每个Tab标签创建一个渲染进程

因为渲染进程所有的内容都是通过网络获取的,会存在一些恶意代码利用浏览器漏洞对系统进行攻击,所以运行在渲染进程里面的代码是不被信任的。出于安全考虑,渲染进程都是运行在沙箱模式下。

  • 网络进程:加载网络资源

  • GPU进程:绘制UI界面

  • 插件进程:负责插件的运行

渲染进程中的线程

  • GUI渲染线程:解析HTML、CSS,生成待绘制列表(JS线程互斥)

  • JS引擎线程:解析运行JS代码

  • 定时器线程:setTimeout和setInterval

  • 事件触发线程:用来控制事件循环

  • 异步HTTP线程:处理异步请求回调

  • 合成线程:将图块转位图

  • IO线程:进行进程间通信

内核和JS引擎

浏览器内核/渲染引擎JavaScript引擎
Chromewebkit->BlinkV8
FireFoxGeckoSpiderMonkey
SafariwebkitJavaScriptCore
EdgeEdgeHTMLChaKra
IETridentJScript

本地存储

Cookie

cookie主要用于实现状态管理,弥补HTTP的不足

缺点:

  • 大小有限制,最多只能存储4KB的cookie
  • 存在性能缺陷,只要是同一域名的请求,就会携带所有的cookie
  • 安全漏洞,在客户端和服务端直接明文传输,而且HttpOnly为false时,可通过js获取cookie

1737930fe4756d53.png

属性:

Path指定的URL路径才能发送Cookie首部

比如设置 Path=/docs,
/docs/Web/ 下的资源会带 Cookie 首部,
/test 则不会携带 Cookie

Expires/Max-Age用于设置 Cookie 的过期时间。缺省值为会话级

Set-Cookie: id=aad3fWa; Expires=Wed, 21 May 2020 07:28:00 GMT;

Set-Cookie: id=a3fWa; Max-Age=604800;

Secure的 Cookie 只应通过被HTTPS协议加密过的请求发送给服务端

HttpOnly属性可以防止客户端脚本通过 document.cookie 等方式访问 Cookie。防止XSS攻击

SameSite属性可以让 Cookie 在跨站请求时不会被发送。防止CSRF攻击

1737930fd2b1b628.png

WebStorage

localStorage和sessionStorage

  • 容量上限也为 5M
  • 只存在客户端,默认不参与与服务端的通信
  • 针对一个域名
分类生命周期容量存储位置
Cookie过期时间,默认会话级4KB客户端和服务端
sessionStorage会话级5M客户端
localStorage持久级5M客户端

IndexDB

indexedDB:浏览器中的非关系型数据库,键值对存储,数据库读写的异步操作,无法访问跨域的数据库

传送门👉 MDN IndexedDB

缓存

是否需要发送HTTP请求区分强缓存和协商缓存

强缓存

HTTP/1.0 Expires字段(过期时间)

HTTP/1.1 Cache-Control字段

1681467d825b2ebe.png

协商缓存

Last-Modified和If-Modified-Since「最后修改时间」

ETag和If-None-Match「根据当前文件的内容,对文件生成唯一的标识」

缓存位置

service worker

独立线程,设计请求拦截,必须HTTPS保障安全

先注册Service Worker,然后监听install事件,下次访问的时候就通过拦截请求查询是否缓存

Memory Cache

将资源缓存在了内存中。内存缓存的控制权在浏览器,无法干涉。

Disk Cache

存储在硬盘中的缓存

Push Cache

服务器推送,HTTP/2,当以上都没命中时才使用属会话级

1.对于大文件来说,大概率是不存储在内存中的,反之优先

2.当前系统内存使用率高的话,文件优先存储进硬盘

缓存策略

  1. 频繁变动的资源
Cache-Control: no-cache
  1. 不常变化的资源
Cache-Control: max-age=31536000
  • 更新版本的时候,顺便把静态资源的路径改了

  • HTML:使用协商缓存

  • CSS&JS&图片:使用强缓存,文件命名带上hash值

垃圾回收

新生代下浏览器可分配内存,64位下64M,32位16M

内存泄漏

通常定义变量的时候就完成内存分配,使用的时候完成对内存的读写。

造成内存泄漏原因:

  • 多余的全局变量的引用
  • 闭包
  • 没有清理的 DOM 元素
  • 被遗忘的定时器和回调
  • 监听事件

GC算法

引用计数让活动对象,通过计数器,记录有多少在引用自己,当计数器变为0里立刻回收

标记-清除(V8) 从根开始对所有活动对象及其子对象打上标记,再次遍历,把没有引用的对象连接到空闲链路上,等待GC

复制将堆分为两个大小相同的空间 From 和 To, 利用 From 空间进行分配,当 From 空间满的时候,GC将其中的活动对象复制到 To 空间,清空 From ,然后两个互换,完成GC

参考

从URL输入到页面呈现发生了什么

网络请求

  1. 处理用户输入

判断是搜索内容还是URL地址

  1. 构建请求

请求行

GET /index HTTP/1.1
  1. 查找缓存

强缓存,不需要发送HTTP请求

  1. DNS解析

域名解析出IP和端口号

关于DNS,可以看看👉阮老师的DNS原理入门

  1. *等待TCP连接

Chrome同一域名下最多支持建立6个TCP连接

  1. 建立TCP连接

面向连接的(3次握手4次挥手),可靠的(记录状态,可控),基于字节流(数据包到字节流)的传输层通行协议

应用层:HTTP,请求行 + 请求头 + 空行 + 请求体

传输层:TCP,HTTP + TCP头部(源端口号、目的程序端口号和用于校验数据完整性的序号)

网络层:数据包 +(源IP地址和目的IP地址)

物理层:传输数据
  1. 发送HTTP请求
请求行 + 请求头 + 空行 + 请求体
  1. 服务端处理请求

NodeJS/Java

  1. 服务端返回(断开连接)
响应行 + 响应头 + 空行 + 响应体

// 响应行
HTTP/1.1 200 OK

页面渲染

  1. 构建DOM树

字节->字符->令牌->节点->DOM

常规的编程语言都是上下文无关的,而HTML却相反,也正是它非上下文无关

解析算法: 标记化->建树

  1. 样式计算

格式化样式表->标准化样式表->计算每个节点样式(层叠、继承)

  1. 布局树
DOM Tree               
      \            
       ->  Render Tree
      /            
CSSOM 

DOM Tree               
      \            
       ->  Layout Tree
      /            
styleSheet
  • 遍历DOM树可见节点,并把这些节点加到布局树中
  • 对于不可见的节点,head,meta标签等都会被忽略
  1. 分层

3D变换、z-index

新图层的创建,显式合成和隐式合成

显式合成: 1.层叠上下文2.裁剪

  1. 绘制

图层拆分为很小的绘制指令

  1. 分块

通过视口,用户只能看到页面的很小一部分,层划分为图块

7.光栅化

指将图块转换为位图。渲染进程把生成图块的指令发送给 GPU,然后在 GPU 中执行生成图块的位图,并保存在 GPU 的内存中

  1. 合成

栅格化操作完成后,合成线程会生成一个绘制命令,即"DrawQuad",并发送给浏览器进程

浏览器进程中的viz组件接收到这个命令,根据这个命令,把页面内容绘制到内存,也就是生成了页面

1732ec3500972dcc.jpg

利用 CSS3 的transform、opacity、filter这些属性,更改了一个既不要布局也不要绘制的属性,那么渲染引擎会跳过布局和绘制,直接执行后续的合成操作

  • 在合成的情况下,直接跳过布局和绘制流程,进入非主线程处理部分,即直接交给合成线程处理。
  • 充分发挥GPU优势,合成线程生成位图的过程中会调用线程池,并在其中使用GPU进行加速生成,而GPU 是擅长处理位图数据的。
  • 没有占用主线程的资源,即使主线程卡住了,效果依然流畅展示。

实践

  • 使用createDocumentFragment进行批量的 DOM 操作
  • 对于 resize、scroll 等进行防抖/节流处理。
  • 动画使用transform或者opacity实现
  • 将元素的will-change 设置为 opacity、transform、top、left、bottom、right 。这样子渲染引擎会为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。
  • 对于不支持will-change 属性的浏览器,使用一个3D transform属性来强制提升为合成 transform: translateZ(0);
  • rAF优化等等