浏览器总结

9/10/2022

# 浏览器兼容性问题

  1. CSS Hack

    CSS hack是通过在CSS样式中加入一些特殊的符号也就是浏览器前缀,让不同的浏览器识别不同的符号(什么样的浏览器识别什么样的符号是有标准的,CSS hack就是让你记住这个标准),以达到应用不同的CSS样式的目的。主要是为了兼容IE低版本

  2. polyfill

    polyfill 是一段代码(或者插件),提供了那些开发者们希望浏览器原生提供支持的功能。程序库先检查浏览器是否支持某个API,如果不支持则加载对应的 polyfill。比如,html5的storage。不同浏览器,不同版本,有些支持,有些不支持。

  3. PostCSS

    可以理解为CSS的Babel工具,拥有强大的插件生态系统来分别做不同的任务.

上述都可以在webpack打包中配置使用.

# 浏览器优化

减少http请求次数:精灵图、base64格式、使用HTTP2、善用强缓存、协商缓存

减少传输时间:cdn、gizp压缩

减少渲染时间:减少回流(重排的次数)、开启服务端渲染

图片优化:懒加载、base64格式、使用webp格式图片

dom操作方面:尽量少操作、使用事件委托

js引擎方面:使用事件委托操作dom、使用web worker进行长时间脚本的运行

# 浏览器安全

  1. 跨站脚本攻击(XSS:Cross Site Script 为了与css区分)

    解释:是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害用户的数据安全。

    XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。

    • 存储型 XSS 攻击:黑客将恶意代码储存到存在漏洞的服务器,浏览器访问含有恶意代码的页面,浏览器上传用户信息到而已服务器。
    • 反射型XSS攻击:用户将一段含有恶意代码的请求提交给 Web 服务器,Web 服务器接收到请求时,又将恶意代码反射给了浏览器端,这就是反射型 XSS 攻击。
    • 基于 DOM 的 XSS 攻击:通过修改原始客户端脚本所使用的DOM环境(在受害者的浏览器中)来执行有效负载。也就是说,页面本身不会更改,但由于对DOM环境的恶意修改,页面中包含的客户端代码以意外的方式运行。

    防范:

    • 对用户的输入进行转义
    • 开启HttpOnly:true、验证码机制,防止脚本冒充用户
    • Content-Security-Policy:响应头字段(csp内容安全策略,指定有效的域、即只执行哪些js脚本,来防止攻击)
  2. 跨站请求伪造(CSRF:Cross-site request forgery)

    解释:攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的

    防范:

    • 请求来源认证,在HTTP请求头中有一个字段叫Referer,它记录了请求的来源地址。 服务器需要做的是验证这个来源地址是否合法,如果是来自一些不受信任的网站,则拒绝响应。
    • token:使用tocken来代替cookie
    • cookie字段设置HttpOnly:true,恶意脚本则无法通过js脚本获取修改cookie
    • cookie字段设置sameSite: strict,cookie在跨站请求时不会被发送

# 面试题

  1. 从输入URL到页面加载的全过程。

    网络请求资源阶段

    1. 构建请求,查找强缓存(根据Expires、Cache-Control头)

    2. DNS解析

      从域名 -> IP地址的解析。如果域名已经被解析过,那么会查找缓存。具体的经历是 浏览器缓存 -> 本地hosts文件 -> 本地DNS解析器 -> 本地DNS服务器 -> 其他DNS服务器

    3. 建立TCP连接

      注意,Chrome在同一个域名下最多只能有6个TCP连接,超过则需等待。

      • 通过三次握手建立客户端服务器的连接。
      • 数据传输
      • 断开连接,四次挥手
    4. 是否建立https连接

    5. 发送HTTP请求(数据传输还未开始)

      携带请求行、请求头、请求体向服务器发送请求。

    6. 网络响应

      网络响应也包含了三个部分:响应行响应头响应体

      当响应结束后判断Connection字段,判断是否未keep-alive连接,若是则是建立的持久性连接.

    浏览器解析渲染资源阶段

    渲染阶段 (opens new window)

    1. 浏览器接收数据

      一般响应头的Content-Type的值是text/html,那么浏览器便开始进行解析和渲染工作

    2. 构建dom树

      将一系列的字节流转换为dom树的数据结构,本质上是一个以document为根节点的多叉树.

      解析HTML(非上下文无关文法):标记化算法=>构建tokens

      img

    3. 样式计算

      格式化样式表:stylesheets(因为浏览器看不懂css样式文本,所以将其转换成结构化的对象,可以通过document.styleSheets查看)

      标准化样式属性:比如rem->px,bold->700等等

      计算具体样式:比如继承的样式

  2. 构建Layout Tree(布局树)

    1. 遍历生成的 DOM 树节点,并把他们添加到布局树中

      1. 计算布局树节点的坐标位置。

      对于head标签和设置了display: none;的元素并不会放入其中

    2. 建图层树

      浏览器在构建完布局树之后,还会对特定的节点进行分层,构建图层树。

      一般情况下,节点的图层会默认属于父节点的图层,(这些图层也被称作合成层),而有的节点会提升成一个单独的合成层。

      • 显示合成

        1. 拥有层叠上下文的情况

          HTML根元素

          普通元素设置了z-index属性,且其position属性不为static

          opacity属性值不为1

          设置了transform属性

          设置了filter属性

          设置了will-change属性

        2. 需要裁剪的地方

          比如一个div,只有50x50大小,但是放置了很多的文字,那么就需要将超出的文字裁剪。

      • 隐式合成

        接下来是隐式合成,简单来说就是层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层。所以若是嵌套的层级太深,就有可能发生层级大爆炸!当然单独的图层在重绘的时候只会影响本身。

    3. 绘制列表

      接下来渲染引擎会将图层的绘制拆分成一个个绘制指令,比如先画背景、再描绘边框......然后将这些指令按顺序组合成一个待绘制列表,然后进行绘制。

    4. 生成图块最终显示

      将图层分块并优先生成视口附近的图块,并交给显示器进行显示。