只针对自己不太熟或者面试常问的有针对性的整理

浏览器架构

现代浏览器的多进程架构如下

多进程架构的优势:

各个进程相互独立,不会互相影响,不会因为一个进程的崩溃而影响整个浏览器的运行

浏览器主进程: 负责各个页面的展示交互

渲染进程: js引擎等

GPU进程:绘制ui界面

网络进程: 负责网络资源加载,浏览器的跨域从渲染进程发起,被网络进程拦截

插件进程: 负责插件运行

JavaScript单线程模型

  1. GUI线程与js引擎线程互斥

  2. js会阻塞页面加载

  3. webWorker可以再开启一个线程,但是这个线程由主线程控制,且不能操作DOM,但是webWorker需要通信,通信时长如果大于线程执行之间将得不偿失。

渲染机制

基本流程

  1. 解析HTML生成DOM
  • 期间如果遇到脚本(js或者其他)那么暂停解析,加载脚本,加载完重新构建DOM
  1. 解析CSS生成CSSOM

  2. DOM树CSSOM树合并生成渲染树

  3. 渲染树进行布局layout,计算节点的位置大小等等

  4. 调用GPU绘制,这个过程称为重绘

重绘回流

基本概念

回流:会计算布局的大小位置,重新生成渲染树

  • 局部回流: 外层dom大小位置不变化,只变化了内层的

  • 全局范围:从根节点开始回流

重绘:只更改外观,不更改布局

针对回流优化

  1. 不要直接修改DOM中会改变定位或者大小的属性

  2. 不要过度的获取计算DOM的位置,大小

  3. visibility取代display: none

  4. 频繁运行的动画使用requestAnimationFrame或者变成一个新的图层

变图层的方式:

  • 3D 变换:translate3dtranslateZ

  • will-change

  • video、iframe 标签

  • position: fixed

与EventLoop的关系

requestAnimationFrame是一个能让js线程和浏览器交互的方法,这个函数传入的方法可以在浏览器重绘前调用,下面写一个简单的demo,让浏览器自己决定函数的触发时机保证不卡顿

1
2
3
4
5
6
7
8
9
10
11
12
let count = 0;
let start = 0;
let ref;

function animation(temp){
if(temp - start > 100){
start = temp;
count++
}
ref = window.requestAnimationFrame(animation)
}
ref = window.requestAnimationFrame(animation)

其余渲染优化

  1. script标签尽量放在后面,最好支持异步加载,最好支持延迟加载

  2. 尽可能快的加载CSS样式表,避免js加载时样式表还没加载完

  3. 适当使用图层

  • 浏览器标准流可以视为一个图层,我们可以手动创建图层,脱离标准流,脱离标准流的图层会单独渲染,因此如果遇到渲染麻烦的图层我们可以单独为其创建一个图层渲染,但是不要过度使用,渲染本身也耗性能

注意点:

  1. CSSOM树的构建会影响渲染树的生成,因此CSS会影响页面渲染

  2. HTML标签遇到script标签会暂停构建,加载完后再去构建DOM

  3. script标签引入的js文件,也需要在css样式表加载完之后才会执行

Load 和 DOMContentLoaded

Load是等HTML、CSS、JS、图片等资源都加载完时触发,可以用来计算首屏渲染时间

DOMContentLoadedHTML解析完成触发,不需要等待CSS、JS、图片

浏览器缓存

强缓存:Cache-ControlExpire

协商缓存:If-none-match配合EtagIf-modified-since配合last-modified

优先强缓存,然后协商缓存

存储方案

Cookie:小 4k左右、会带到请求头
localStorage: 5m,需要手动清理
sessionStorage 5m,一直存在

跨域

详细看HTTP

安全(XSS和CSRF)

XSS:代码注入

  • 持久型:数据库代码注入
  • 非持久: url代码注入(浏览器自动防范)

CSP: 白名单(设置外部资源访问限制),meta标签可以做<meta http-equiv="Content-Security-Policy">

CSRF: 跨站请求伪造,本站请求黑客服务器的方式来获取用户的信息

  • cookie设为同域
  • 请求带上token

    从输入URL到页面展示的过程(经典面试题)

  1. 合成url,判断是否是一个合法的域名,非合法就调用浏览器默认搜索功能,合法就跳转到对应的网站
  2. DNS检索,检索优先从缓存中拿(浏览器缓存中 -> 本地HOST -> 本地DNS解析缓存 -> 本地DNS服务器),缓存中如果没有,依次查找根域名服务器、顶级域名服务器、二级域名服务器
  3. 建立TCP连接,TCP连接主要是三次握手
  • 第一次:客户端发送标记位SYN, seq = p
  • 第二次:服务端响应ACKack = p + 1,请求建立连接标记位SYN seq = q
  • 第三次: 客户端响应标记位为ACK ack = q + 1
  1. 获取文件,优先从缓存中获取文件,优先强缓存,然后协商缓存

  2. 断开连接,TCP四次挥手

  • 客户端发出标记位FIN,请求关闭
  • 服务端发送标记位ACK,表示收到
  • 服务端发出标记位FIN,表示可以关闭
  • 客户端发出标记位ACK,表示收到
  • 客户端等待两个MSL后断开连接
  1. 获取文件后,解析HTML,渲染页面
  • 解析HTML,生成 DOM 树, 解析CSS,生成CSSOM
  • 合并生成render树
  • 交由GPU渲染页面
  • 交给浏览器绘制展示到页面上

    图层

层叠上下文是HTML元素的三维概念,这些HTML元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的z轴上延伸,HTML元素依据其自身属性按照优先级顺序占用层叠上下文的空间。

拥有层叠上下文属性的元素会被提升为单独的一层。
拥有层叠上下文属性:

  • 根元素 (HTML),
  • z-index 值不为 "auto"的 绝对/相对定位元素,
  • position,固定(fixed) / 沾滞(sticky)定位(沾滞定位适配所有移动设- 备上的浏览器,但老的桌面浏览器不支持)
  • z-index值不为 "auto"flex 子项 (flex item),即:父元素 - display: flex|inline-flex
  • z-index值不为"auto"grid子项,即:父元素display:grid
  • opacity 属性值小于 1的元素(参考 the specification for - opacity),
  • transform 属性值不为 "none"的元素,
  • mix-blend-mode 属性值不为 "normal"的元素,
  • filter值不为"none"的元素,
  • perspective值不为"none"的元素,
  • clip-path值不为"none"的元素
  • mask / mask-image / mask-border不为”none”的元素
  • isolation 属性被设置为 "isolate"的元素
  • will-change 中指定了任意CSS属性
  • -webkit-overflow-scrolling 属性被设置 “touch”的元素
  • contain属性值为"layout""paint",或者综合值比如"strict""content"

requestAnimationFrame 和 requestIdleCallback

requestAnimationFrame浏览器渲染前调用,60刷新率大概为16.7ms

requestIdleCallback,浏览器两帧间的空闲时间调用