【前端开发】| 前端中浏览器中的那些点点滴滴

297 阅读13分钟

浏览器内核

浏览器内核主要分为两个部分:渲染引擎、js引擎;

  • 渲染引擎: 负责取得网页的内容(html css img ...),以及计算网页的显示方式,渲染成DOM 树,然后会输出至显示器或者打印机。浏览器的内核不同对于网页的语法解释也不同,所以渲染的效果也不一样;
  • js引擎: 解析和执行javascript,将javascript代码翻译成CPU指令来执行;
  • 主流浏览器内核:
    • IE: trident 内核;
    • Firefox: gecko 内核;
    • Safari:webkit 内核;
    • Opera:以前是presto内核,现在改用为Google-Chrome的Blink内核;
    • Chrome:Blibk内核,它是基于webkit,由Google和Opera Software共同开发;

浏览器存储方式

特性cookielocalSoragesessionStorageindexedDB
数据生命周期一般由服务器生成,可以设置过期时间除非被清除,否则会一直存在页面关闭就被清理除非被清理·,否则会一直存在
数据存储大小4K5M5M无限
与服务端通信每次都会携带在header中,对于请求性能影响不参与不参与不参与

cookies , sessionStorage 和 localStorage 的区别

  • cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密)
  • cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递(优化点)- sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
  • 存储大小:
    • cookie 数据大小不能超过4k
    • sessionStorage 和 localStorage虽然也有存储大小的限制,但比 cookie 大得多,可以达到5M或更大
  • 有期时间:
    • localStorage 存储持久数据,浏览器关闭后数据不丢失 除非主动删除数据;
    • sessionStorage 数据在当前浏览器窗口关闭后自动删除;
    • cookie 设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭

localStorage 自带getItem(取数据)和setltem(存数据)来存取数据;

  • localStorage 只能存字符串,存取 JSON 数据需配合 JSON.stringify() 和 JSON.parse();遇上禁用 setItem 的浏览器,需要使用 try...catch 捕获异常
  • cookie 原本并不是用来储存的,而是用来与服务端通信的,需要存取需自行封装 api。

HTTP 的请求方式场景

  • Get:获取数据通常(查看数据)-查看;
  • POST: 向服务器提交数据通常(创建数据)-create;
  • PUT: 向服务器提交数据通常(更新数据)-update,与POST方法很像,也是提交数据,但PUT制定了资源在服务器上的位置,常用在修改数据;
  • HEAD:只请求页面的首页信息;
  • DELETE: 删除服务器上的资源;
  • OPTIONS: 用于获取当前URL 支持的请求方式;
  • TRACE: 用于激活一个远程的应用层请求消息回路;
  • CONNECT: 把请求链接转换到透明的TCP/IPd的通道;

HTTP 状态码

  • 1XX: 消息状态码
    • 100: continue 继续,一般在发送post请求时,已发送了http haeder 之后服务端将返回此信息,表示确认,之后发送具体参数信息;
  • 2XX: 成功状态码
    • 200:ok正常返回信息;
    • 201:created 请求成功并且服务端创建了新资源;
    • 202:accepted 服务器已经接收请求,但尚未处理;
  • 3XX:重定向
    • 301:move per请求的网页已经永久重定向;
    • 302:found临时重定向;
    • 303:see other临时冲重定向,且总是使用get请求新的url;
    • 304: not modified 自从上次请求后,请求的网页未修改过;
  • 4XX:客户端错误
    • 400:bad request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求;
    • 401:unauthorized 请求未授权;
    • 403:forbidden禁止访问;
    • 404:not found 找不到如何与url匹配的资源;
  • 5XX:服务器错误
    • 500:internal server error最常见的服务器端的错误;
    • 503:service unacailable服务器端暂时无法处理请求(可能是过载活维护)

简述浏览器处理过程:

一般我们从浏览器地址栏输入URL后,就等待浏览器给我们返回想要的东西,而这个过程中,浏览器进行了下面一系列操作:

  • 浏览器根据请求的URL 交给 DNS域名解析,找到真实 IP,向服务器发起请求;
  • 服务器交给后台处理完成后返回数据,浏览器接收文件( HTML、JS、CSS 、图象等);
  • 浏览器对加载到的资源( HTML、JS、CSS 等)进行语法解析,建立相应的内部数据结构(如 HTML 的 DOM );
  • 载入解析到的资源文件,渲染页面,完成。

详细描述浏览器的处理过程:

在浏览器地址栏输入URL后:

  • 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤:
    • 如果资源未缓存,发起新请求;
    • 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。
    • 检验新鲜通常有两个HTTP头进行控制 Expires 和 Cache-Control :
      • 2.3.1 HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期
      • 2.3.2 HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间
  • 浏览器解析URL获取协议,主机,端口,path
  • 浏览器组装一个HTTP(GET)请求报文
  • 浏览器获取主机ip地址,过程如下:
    • 浏览器缓存
    • 本机缓存
    • hosts文件
    • 路由器缓存
    • ISP DNS缓存
    • DNS递归查询(可能存在负载均衡导致每次IP不一致)
  • 打开一个socket与目标IP地址,端口建立TCP链接,三次握手 如下:
    • 客户端发送一个TCP的SYN=1,Seq=X的包到服务器端口
    • 服务器发回SYN=1,ACK=x+1,Seq=Y的相应包
    • 客户端发送ACK=Y+1,Seq=z
  • TCP链接建立后发送HTTP请求
  • 服务器接收请求后解析,将请求转发到服务器程序,如虚拟主机使用HTTP Host头部判断请求的服务程序
  • 服务器检测HTTP请求头是否包含缓存验证信息,如果验证缓存新鲜,返回304等对应状态
  • 出合理程序读取完整请求并准备HTTP相应,可能需要查询数据库等操作
  • 服务器将相应报文通过TCP链接发送回浏览器
  • 浏览器接收HTTP相应,然后根据情况选择关闭TCP链接或者保留重用,关闭TCP链接的四次握手如下:
    • 主动方发送Fin=1,ACK=z,Seq=x报文
    • 被动方发送ACK=X+1,Seq=Y报文
    • 被动方发送Fin=1,ACK=X,Seq=Y报文
    • 主动方发送ACK=Y,Seq=x报文
  • 浏览器检查相应状态码
  • 如果资源可缓存,进行缓存
  • 对相应进行解码
  • 根据资源类型决定如何处理
  • 解析HTML文档,构建DOM树,下载资源,构建CSSOM树,执行js脚本,这些操作每月严格的先后顺序
  • 构建DOM树:
    • Tokenizing:根据HTML规范将字符流解析为标记
    • Lexing:词法分析将标记转换为对象并定义属性和规则
    • DOM construction:根据HTML标记关系将对象组成DOM树
  • 解析过程中遇到图片、样式表、js文件,启动下载
  • 构建CSSOM树:
    • Tokenizing:字符流转换为标记流
    • Node:根据标记创建节点
    • CSSOM:节点创建CSSOM树
  • 根据DOM喝CSSOM树构建渲染树 - 从DOM树的根节点遍历所有可见节点,不可见节点包括:1) script , meta这样本身不可见的标签。2)被css隐藏的节点,如 display: none - 对每一个可见节点,找到恰当的CSSOM规则并应用 - 发布可视节点的内容和计算样式
  • js解析如下
    • 浏览器创建Document对象并解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loading
    • HTML解析器遇到没有async和defer的script时,将他们添加到文档中,然后执行行内或外部脚本。这些脚本会同步执行,并且在脚本下载和执行时解析器会暂停。这样就可以用document.write()把文本插入到输入流中。同步脚本经常简单定义函数和注册事件处理程序,他们可以遍历和操作script和他们之前的文档内容
    • 当解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器不会停下来等它下载。异步脚本禁止使用document.write(),它们可以访问自己script和之前的文档元素
    • 当文档完成解析,document.readState变成interactive
    • 所有defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用document.write()
    • 浏览器在Document对象上触发DOMContentLoaded事件
    • 此时文档完全解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入并且所有异步脚本完成载入和执行,document.readState变为complete,window触发load事件
  • 显示页面(HTML解析过程中会逐步显示页面)

Cookie的优缺点

  • 优点: 极高的扩展性和可用性
  1. 数据持久性;
  2. 不需要任何服务器资源。 Cookie 存储在客户端并在发送后由服务器读取;
  3. 可配置到期规则。 控制 cookie 的生命期,使之不会永远有效。偷盗者很可能拿到一个过期的 cookie;
  4. 简单性。 基于文本的轻量结构;
  5. 通过良好的编程,控制保存在 cookie 中的 session 对象的大小;
  6. 通过加密和安全传输技术( SSL ),减少 cookie 被破解的可能性;
  7. 只在 cookie 中存放不敏感数据,即使被盗也不会有重大损失;
  • 缺点:
  1. Cookie 数量和长度的限制 。 数量:每个域的 cookie 总数有限。 a). IE6 或更低版本最多 20 个 cookie; b). IE7 和之后的版本最后可以有 50 个 cookie; c). Firefox 最多 50 个 cookie; d). chrome 和 Safari 没有做硬性限制长度:每个 cookie 长度不超过 4KB ( 4096B ),否则会被截掉;
  2. 潜在的安全风险 。 Cookie 可能被拦截、篡改。如果 cookie 被拦截,就有可能取得所有的 session 信息;
  3. 用户配置为禁用 。有些用户禁用了浏览器或客户端设备接受 cookie 的能力,因此限制了这一功能;
  4. 有些状态不可能保存在客户端 。例如,为了防止重复提交表单,我们需要在服务器端保存一个计数器。如果我们把这个计数器保存在客户端,那么它起不到任何作用。

浏览器缓存

浏览器缓存分为强缓存和协商缓存。当客户端请求某个资源时,获取缓存的流程如下:

  • 先根据这个资源的一些 http header 判断它是否命中强缓存,如果命中,则直接从本地获取缓存资源,不会发请求到服务器;
  • 当强缓存没有命中时,客户端会发送请求到服务器,服务器通过另一些 request header验证这个资源是否命中协商缓存,称为http 再验证,如果命中,服务器将请求返回,但不返回资源,而是告诉客户端直接从缓存中获取,客户端收到返回后就会从缓存中获取资源;
  • 强缓存和协商缓存共同之处在于,如果命中缓存,服务器都不会返回资源; 区别是,强缓存不对发送请求到服务器,但协商缓存会。
  • 当协商缓存也没命中时,服务器就会将资源发送回客户端。
  • 当 ctrl+f5 强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存;
  • 当 f5 刷新网页时,跳过强缓存,但是会检查协商缓存;

浏览器渲染步骤

  1. HTML 解析出 DOM Tree
  2. CSS 解析出 Style Rules
  3. 两者关联生成 Render Tree
  4. Layout(布局)根据 Render Tree 计算每个节点的信
  5. Painting 根据计算好的信息进行渲染整个页面

浏览器解析文档的过程中: 如果遇到 script 标签,会立即解析脚本,停止解析文档(因为 JS 可能会改变 DOM 和 CSS,如果继续解析会造成浪费); 如果是外部 script, 会等待脚本下载完成之后在继续解析文档。现在 script 标签增加了 defer 和 async 属性,脚本解析会将脚本中改变 DOM 和 css 的地方> 解析出来,追加到 DOM Tree 和 Style Rules 上

GET 和 POST 请求的区别

  • GET 参数通过 url 传递,POST 放在 body 中。(http 协议规定,url 在请求头中,所以大小限制很小)
  • GET 请求在 url 中传递的参数是有长度限制的,而 POST 没有。
  • GET 在浏览器回退时是无害的,而 POST 会再次提交请求
  • GET 请求会被浏览器主动 cache,而 POST 不会,除非手动设置
  • GET 比 POST 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息
  • 对参数的数据类型,GET 只接受 ASCII字符,而 POST 没有限制
  • GET 请求只能进行 url(x-www-form-urlencoded)编码,而 POST 支持多种编码方式
  • GET 产生一个 TCP 数据包;POST 产生两个 TCP 数据包。对于 GET 方式的请求,浏览器会把 http 的 header 和 data 一并发送出去,服务器响应200(返回数据)。而对于 POST,浏览器先发送 header,服务器响应100 continue,浏览器再发送 data,服务器响应200 ok(返回数据)

什么是reflow

浏览器为了重新渲染部分或整个页面,重新计算页面元素位置和几何结构的进程叫做 reflow . 通俗点说就是当开发人员定义好了样式后(也包括浏览器的默认样式),浏览器根据这些来计算并根据结果将元素放到它应该出现的位置上,这个过程叫做 reflow . 由于reflow是一种浏览器中的用户拦截操作,所以我们了解如何减少 reflow 次数,及DOM的层级,css 效率对 refolw 次数的影响是十分有必要的。 reflow (回流)是导致DOM脚本执行效率低的关键因素之一,页面上任何一个节点触发了 reflow,会导致它的子节点及祖先节点重新渲染。 简单解释一下 Reflow:当元素改变的时候,将会影响文档内容或结构,或元素位置,此过程称为 Reflow。

导致reflow发生的原因

  • 改变窗口大小
  • 改变文字大小
  • 添加/删除样式表
  • 内容的改变,(用户在输入框中写入内容也会)
  • 激活伪类,如:hover操作class属性
  • 脚本操作DOM
  • 计算offsetWidth和offsetHeight
  • 设置style属性