前端缓存 & 浏览器存储


前言

前端缓存 一般用于缓存 一些不常修改的常量数据一些静态资源文件。大部分接口请求的数据都缓存在了服务端,方便统一管理缓存数据。

前端做缓存的必要性:可以缓解服务端的压力,减少带宽的占用,同时也可以提升前端的查询性能。

前端缓存可分为两大类:浏览器存储HTTP 缓存


一、浏览器存储

浏览器存储的分类:

浏览器缓存与本地存储

0、bfcache

浏览器往返缓存–back-forward cache(bfcache)
浏览器的 bfcache 特性

1、WebStorage

WebStorage提供两种类型的API:localStorage 和 sessionStorage。它们均继承自 Storage 类。

Storage 类的主要用途:

  • 提供一种在 cookie 之外存储会话数据的途径;
  • 提供一种可以存储大量的跨会话数据的机制(不会产生跨域)。
  • 与操作 cookie 中的数据不同,由于 Storage 类型的数据不会产生跨域,所以操作它里面的数据的时候不必开启本地服务器(Wampserver)。

Storage 类型只能存储字符串,非字符串的数据在存储之前会被转为字符串。

Storage 类型有以下方法:

  • clear():删除所有值。
  • getItem(name):根据指定的名字 name 获取对应的值。
  • key(index):获得 index 位置处的值的名字。
  • removeItem(name):删除由 name 指定的名值对儿。
  • setItem(name, value):为指定的 name 设置一个对应的值。

其中,getItem()、removeItem() 和 setItem() 方法可以直接调用,也可以通过 Storage 对象间接调用。删除数据的时候还可以使用 delete 操作符直接删除。另外,还可以使用 length 属性来判断有多少名值对儿存放在 Storage 对象中。

在使用 Storage 类型时,建议使用它的方法而不是属性来访问数据,以免某个键会意外重写该对象上已存在的成员

对 Storage 对象进行任何修改都会在 document 对象上触发 storage 事件,这个事件的 event 对象有以下 4 个属性:

  • domain:发生变化的存储空间的域名。
  • key:设置或删除的键名。
  • newValue:如果是设置值,则是新值;如果是删除键,则是 null。
  • oldValue:键被更改之前的值。

可以这样侦听 storage 事件:

EventUtil.addHandler(document, "storage", function(event){
    var event = EventUtil.getEvent(event);
    alert("当前 Storage 对象的域名是:" + event.domain);
});


上述代码中用到的 EventUtil 事件处理程序,详情请戳:js 跨浏览器事件处理程序脚本

但是测试发现,storage 事件并未触发,怎么回事呢?

原来触发 storage 事件是有条件的,必须满足一下条件:

  • 同一浏览器打开了两个同源页面;
  • 其中一个页面修改了localStorage;
  • 另一个网页注册了这个事件。

下面就来介绍,Storage 类的两个实例对象:localStorage 和 sessionStorage。

(1)、sessionStorage 对象

Cookie、Session 和 Token 三种维持用户会话状态的机制

sessionStorage 对象是 Storage 类型的一个实例,拥有 Storage 的所有属性和方法。

sessionStorage 对象用来:存储特定的某个会话的数据。如果需要跨越会话存储数据,请选择 globalStorage 或 localStorage 对象。

sessionStorage 对象的特点:

  • 页面刷新不会影响 sessionStorage 对象中的数据;除 IE 之外,其他浏览器即使崩溃了,重启后也不会影响 sessionStorage 对象中的数据。
  • 因为 sessionStorage 对象绑定于某个服务器会话,所以当文件在本地运行时 sessionStorage 是不可用的。
  • 存储在 sessionStorage 对象中的数据只能由最初给该对象存储的页面能够访问到,所以对多页面应用有限制。

操作 sessionStorage 对象里存储的数据:

// 存储数据
sessionStorage.name02 = "Caocao";
sessionStorage.setItem("name01", "Zhangfei");
// 获取数据
console.log(sessionStorage.name01); // Caocao
console.log(sessionStorage.getItem("name02")); // Zhangfei
// 删除数据
delete sessionStorage.name01;
sessionStorage.removeItem("name02");

(2)、localStorage 对象

localStorage 对象是 Storage 类型的一个实例,拥有 Storage 的所有属性和方法。

localStorage 对象用来:持久保存客户端的数据(数据保留到通过 JavaScript 删除或者是用户清除浏览器缓存)。

localStorage 对象的特点:

  • 必须遵从同源策略(同协议、同域名、同端口),否则会跨域。

操作 localStorage 对象中的数据:

// 存储数据
localStorage.name01 = "Liuibang";
localStorage.setItem("name02", "Zhangliang");
// 获取数据
console.log(localStorage.name01); // Liuibang
console.log(localStorage.getItem("name02")); // Zhangliang
// 删除数据
delete localStorage.name01;
localStorage.removeItem("name02");

localStorage 同时存取储多条数据:

// 存
const data = {
    a: 111,
    b: "333",
    c: false,
};
localStorage.setItem("data", JSON.stringify(data));

// 取
const data = JSON.parse(localStorage.getItem("data"));

2、Cookie

请参见这篇文章:Cookie 的使用

(1)、cookie 与 sessionStorage、localStorage 的对比

cookiesessionStoragelocalStorage
生命周期可以自己设置,默认到浏览器关闭页面关闭就结束除非自己删除,否则一直存在。
存储类型只能存储字符串只能存储字符串只能存储字符串
大小<4KB5MB5Mb
保存地址客户端客户端客户端
安全性
是否存在跨域存在跨域不会跨域存在跨域

Cookie:

  • 用来存储客户端的 HTTP 状态信息。
  • 同一个域名下的 cookie 是共享的。不利于 http 性能的提升,而且不同域名间会产生跨域。
  • 数量受限,大小受限。不同的浏览器对 cookie 都有各自的数量限制,且每个 cookie 只能存储 4KB 大小的数据。
  • 可以设置有效期。关闭浏览器后,没有设置有效期的 cookie 会被清掉,设置了有效期的 cookie 会继续生效,直到过期时自动清掉。

sessionStorage(会话存储):

  • 用于临时保存同一窗口(或标签页)的数据。在关闭窗口后这些数据会自动删除。
  • 只能存储字符串。
  • 不会产生跨域。
  • 同步存储。
  • 大小受限,最多只能存储 5M 。

localStorage(本地存储):

  • 用来持久保存客户端的数据。只要不人为删除数据会一直在。
  • 只能存储字符串。
  • 不会产生跨域。
  • 同步存储。
  • 大小受限,最多只能存储 5M 。

3、IndexedDB

IndexedDB 的特点:

  • 键值对存储:在对象仓库中,数据以“键值对”的形式保存,每一个数据都有对应的键名,键名是独一无二的,不能有重复,否则会抛出一个错误。
  • 支持二进制储存:可存储字符串、二进制数据(ArrayBuffer 对象和 Blob 对象)。
  • 支持异步存储:。
  • 储存空间大:不同浏览器的上限不同。
  • 支持事务:IndexedDB 支持事务,这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。
  • 同域限制: IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。
  • 览器兼容性不好。

IndexedDB 的使用场景:

  • 数据超过了 5M,建议使用 IndexedDB 存储在本地。
  • 数据在 5M 以内,建议使用 localStorage 存储在本地。

与 localstorage 相比,indexedDB 的优势在于:IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。

就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。

4、WebSql

WebSql 于 2010 年被 W3C 废弃,但主流浏览器都已经有了相关的实现。
现在官网已经停止维护 webSQL 了,转为维护 indexedDB。

WebSql 是本地数据存储方案之一。

WebSQL 更准确的说是 WebSQL DB API,它是一种操作本地数据库的网页 API 接口,通过 API 可以完成客户端数据库的操作。

当我们使用 WebSQL 的时候,可以方便地用 SQL 来对数据进行:增、删、改、查。而这些浏览器客户端,比如 Chrome 和 Safari 会用 SQLite 实现本地存储,微信就采用了 SQLite 作为本地聊天记录的存储。

WebSQL 的简单使用
WebSQL:如何在H5中存储一个本地数据库?

5、H5 webapp 的离线缓存

HTML5 的应用缓存(简称 app cache)是专门为开发离线 web 应用而设计的,确保离线时资源可用。目前,Application Cache 方案已经从 W3C 标准里移除了。

建议使用 PWA 离线缓存 方案来实现。


二、HTTP 缓存

HTTP 缓存是通过设 置 HTTP Header 来实现的。

HTTP 缓存分类:

  • 强缓存:在缓存期间不需要请求。
    • Pragma
    • Cache-Control
    • Expires
  • 协商缓存:如果缓存过期了,就需要发起请求验证资源是否有更新。当浏览器发起请求验证资源时,如果资源没有做改变,那么服务端就会返回 304 状态 码,并且更新浏览器缓存有效期。
    • ETag/If-Not-Match
    • Last-Modified/If-Modified-Since

强缓存 与 协商缓存的对比:

  • 共同点:都是从客户端缓存中读取资源。
  • 区别是:强缓存不会发请求,协商缓存会发请求

1、强缓存

强缓存指的是:先不向服务器发送请求,而是直接从缓存中读取资源。

  • 若缓存有效,则状态码是 200,并且 Size 显示 from disk cache(硬盘缓存)或 from memory cache(内存缓存)。
  • 若缓存已过期,才会向服务器发送请求。

强缓存的 2 种实现方式:利用 Expires 或者 Cache-Control 这两个 HTTP Response Header 实现的,它们都用来表示资源在客户端缓存的有效期。

  • Expires:Expires 属性是一个绝对时间。
  • Cache-Control:Cache-Control 属性是一个相对时间,即一个过期时间大小,与协商缓存一样。可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。

HTTP 强缓存的设置方式有多种,按照优先级从大到小依次是:S-maxage > max-age > Expires > 预估过期时间

(1)、Expires(一个绝对时间)

在这里插入图片描述
Expires 属性是一个绝对时间。

Expires 缓存的弊端:

  • 受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
  • 到期时间由服务端生成的,但是客户端时间可能跟服务端时间有误差,这就会导致缓存命中的误差。

(2)、Cache-Control(一个相对时间)

HTTP 1.1 的版本,使用 Cache-Control 替代了 Expires 做浏览器的强制缓存。

在这里插入图片描述
Cache-Control 属性是一个相对时间,即一个过期时间大小,与协商缓存一样。可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。

Cache-Control 可以在 请求头 或者 响应头 中设置,并且可以组合使用多种指令:

  • 常见的取值有:private、public、no-cache、max-age,no-store。
  • 默认取值为:private
  • Cache-Control 多种指令的含义:
    • private: 客户端可以缓存。
    • public: 客户端和代理服务器都可缓存。
    • max-age=xxx: 缓存的内容将在 xxx 秒后失效,需要重新请求。
    • s-max-age=xxx: 缓存的内容将在 xxx 秒后失效,需要重新请求。
    • no-cache: 需要使用协商缓存来验证缓存数据。
    • no-store: 所有内容都不会缓存(强制缓存、协商缓存都不会触发)。
    • max-stale=xx:xxx秒内即使缓存过期,也使用该缓存。
    • min-fresh=xx: 希望在xx秒内获取获取最新响应。

用 Cache-Control 实现 强缓存 的流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。

2、协商缓存

协商缓存指的是:与服务端协商之后,通过协商结果来判断是否使用本地缓存。

协商缓存的 2 种实现方式:

  • Last-Modified/If-Modified-Since:可以基于请求头部中的 If-Modified-Since 字段与返回头部中的 Last-Modified 字段实现——基于时间实现
  • ETag/If-None-Match:也可以基于请求头部中的 If-None-Match 字段与返回头部中的 ETag 字段来实现——基于唯一标识实现——可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。

优先级:ETag/If-None-Match > Last-Modified/If-Modified-Since

这 2 种协商缓存的 实现流程 如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 ETag 唯一标识,这个唯一标识的值是根据当前请求的资源生成的;
  • 当浏览器再次请求访问服务器中的该资源时,会在 Request 头部加上 If-None-Match 字段,该字段的值就是 Response 头部加上 ETag 唯一标识;
  • 服务器再次收到请求后,会根据请求中的 If-None-Match 值与当前请求的资源生成的唯一标识进行比较,如果值相等,则返回 304 Not Modified,如果不相等,则在 Response 头部加上新的 ETag 唯一标识,并返回 200 状态码和请求的资源;
  • 如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。

二者的区别:

  • ETag/If-None-Match:准确度更高,Last-Modified 只能精确到秒级。
  • Last-Modified/If-Modified-Since:性能更好(不一定,当资源被重复生成,而内容不变 Etag 更适合)。

可以将 Last-Modified 与 ETag 是一起使用——服务器会优先验证 ETag,一致的情况下,才会继续比对 Last-Modified,最后才决定是否返回 304。

(1)、Last-Modified / If-Modified-Since(资源最后修改时间)

Last-Modified(资源最后修改时间):是该资源文件最后一次更改时间,由服务器生成,并在 response header 里返回给客户端。

当我们第一次发出请求时,Last-Modified 由服务器返回。例如:

Last-Modified: Fri, 23 Jul 2017 01:47:00 GMT

同时,浏览器会将这个值保存起来,下一次发送请求时,放到 request headr 里的 If-Modified-Since 里。服务器在接收到后也会做对比:

  • 如果相同,就说明该资源没有被修改过,命中协商缓存,返回状态码 304,通知客户端继续使用缓存资源。
  • 如果不相同,就说明资源被修改过,返回状态码 200,以及最新资源。

客户端发送的这个字段一般有两种:

  • If-Modified-Since: Last-Modified-value:该字段告诉服务器如果客户端传来的最后修改时间和服务器上的一致,直接返回 304 状态码即可,当前各大浏览器均是使用该字段来向服务器传递保存的 Last-Modified 的值。如果时间不一致的话,服务器会返回所有的这个资源并返回 200 状态码。
  • If-Unmodified-Since: Last-Modified-value:该字段告诉服务器如果客户端传来的最后修改时间和服务器上的不一致,则直接返回 412 状态码(先决条件不成立——首部字段 If-Unmodified-Since 或 If-None-Match 规定的先决条件不成立)。

Last-Modified 的弊端,比如:

  • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
  • 一些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
  • 一些服务器不能精确的得到文件的最后修改时间。

为解决上面这些问题,HTTP 新增了 ETag 字段来标注资源的唯一性。

(2)、Etag / If-None-Match(资源的唯一标识)

Etag(资源的唯一标识):ETag 是资源的唯一标识,由服务器生成,并在 response header 里返回给客户端。

当我们第一次发出请求时,ETag 由服务器返回。例如:

ETag: W/"5ce-164c641f628"

同时,浏览器会将这个值保存起来,下一次发送请求时,放到 request headr 里的 If-None-Match 里。服务器收到请求后,将 If-None-Match 的值与被请求资源的标签进行比对:

  • 如果相同,就说明该资源没有被修改过,命中协商缓存,返回状态码 304,通知客户端继续使用缓存资源。
  • 如果不相同,就说明资源被修改过,返回状态码 200,以及最新资源。

客户端发送的这个字段一般有两种:

  • If-None-Match: ETag-value:告诉服务端如果 ETag 没匹配上需要重发资源数据,否则直接回送304 和响应报头即可。(当前各浏览器均是使用的该请求首部来向服务器传递保存的 ETag 值)。
  • If-Match: ETag-value:该字段告诉服务器如果客户端传来的 Etag 值跟服务器上的不一致,则直接返回 412 状态码(先决条件不成立——首部字段 If-Unmodified-Since 或 If-None-Match 规定的先决条件不成立)。

3、强缓存 与 协商缓存一起使用

强缓存 与 协商缓存 最好是配合在一起用,争取最大化的减少请求,利用缓存,节约流量

浏览器缓存过程(强缓存 与 协商缓存一起使用):

  • 浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间(要与Cache-Control和Expires对比)一并缓存;
  • 下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过Cache-Control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用Expires判断是否过期);
  • 如果时间过期,服务器则查看header里的If-None-Match和If-Modified-Since ;
  • 服务器优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回 200;
  • 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回 200。

三、按缓存位置区分浏览器缓存

无论是强缓存还是协商缓存,资源缓存的位置是不同的。常见的比如:from memory cache 和 from disk cache。

按缓存位置可以将浏览器缓存分为以下 4 种,按照优先级从大到小依次是:Service Worker > Memory Cache > Disk Cache > Push Cache

如果以上四种缓存都没有命中的话,那么只能发起请求来获取资源了。

1、Service Worker

开源实验室 已启用 Service Worker,现在只要你访问过的文章,在浏览器二次访问均可离线访问。
PWA 就是基于 service Worker 缓存实现的。

在这里插入图片描述

service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存
哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。

service Worker 的特点:

  • 借鉴了 Web Worker
  • 传输协议必须是 HTTPS。
  • 可以自由的控制缓存哪些文件、如何匹配读取缓存。
  • 且缓存是持续性的。

当 Service Worker 没有命中缓存的时候,我们需要去调⽤ fetch 函数获取数据。也就是说,如果我们没有在 Service Worker 命中缓存的话,会根据缓存查找优先级去查 找数据。但是不管我们是从 Memory Cache 中还是从网络请求中获取的数据,浏览器都会显示我们是从 Service Worker 中获取的内容。

【推荐阅读】
Service Worker:让网页无网络也能访问

2、Memory Cache——内存缓存

在这里插入图片描述

Memory Cache 也就是内存中的缓存,读取内存中的数据肯定比磁盘快。但是内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放⽽释放。 ⼀旦我们关闭 Tab 页面,内存中的缓存也就被释放了。

Memory Cache 的特点:

  • 读取效率高,但是持续时间短,会随着进程的释放而释放。
  • 几乎所有的请求资源都能进入 memory cache,比如:通过 preload 和 prefetch 预加载的资源。
  • 在从 memory cache 读取缓存时,浏览器会忽视 Cache-Control 中的一些 max-age、no-cache 等头部设置,除非设置了 no-store 这个头部设置。

3、Disk Cache——硬盘缓存

在这里插入图片描述

Disk Cache 也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中, 比之 Memory Cache 胜在容量和存储时效性上。

Disk Cache 的特点:

  • 持续时间长,是实际存在于文件系统中的缓存。
  • 比内存缓存慢,但是优势在于存储容量大。

在所有浏览器缓存中, Disk Cache 覆盖⾯基本是最⼤的。它会根据 HTTP Herder 中的字段判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求。并且即使在跨站点的情况下,相同地址的资源⼀旦被硬盘缓存下来,就不会再次去请求数据。

4、Push Cache(了解)

Push Cache(推送缓存)是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在 Chrome 浏览器中只有 5 分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

Push Cache 的特点:

  • 所有的资源都能被推送,并且能够被缓存,但是 Edge 和 Safari 浏览器支持相对比较差。
  • 可以推送 no-cache 和 no-store 的资源。
  • 一旦连接被关闭,Push Cache 就被释放。
  • 多个页面可以使用同一个HTTP/2的连接,也就可以使用同一个Push Cache。这主要还是依赖浏览器的实现而定,出于对性能的考虑,有的浏览器会对相同域名但不同的tab标签使用同一个HTTP连接。
  • Push Cache 中的缓存只能被使用一次。
  • 浏览器可以拒绝接受已经存在的资源推送。
  • 你可以给其他域名推送资源。

    【推荐阅读】
    再谈ServerPush,Push or Not Push
    HTTP/2 push is tougher than I thought

四、如何设置“不使用”缓存

  • Cache-Control 设置为:
Cache-Control: no-cache, no-store, must-revalidate
  • Expires 设为当前时间之前。
  • 在引用js、css文件的url后边加上 ?+Math.random()。例如:
<script type=“text/javascript” src=/js/test.js?+Math.random()></script> 
  • 设置html页面不让浏览器缓存的方法:
<meta http-equiv="pragma" content="no-cache"> 
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate"> 
<meta http-equiv="expires" content="Wed, 26 Feb 1997 00:00:00 GMT">
  • 在用 Ajax 发起请求的时候设置请求头 cach: false

五、刷新对缓存的影响

  • 正常刷新(地址栏访问):强制缓存 和 协商缓存都有效。
  • 手动刷新(F5 刷新):强制缓存失效、协商缓存有效。
  • 强制刷新(ctrl + F5 强制刷新):强制缓存 和 协商缓存都失效。




【参考文章】
浏览器缓存原理总结
前端浏览器缓存知识梳理
浏览器缓存看这一篇就够了
彻底理解浏览器的缓存机制
彻底弄懂前端缓存
理解 Web 缓存
设计一个无懈可击的浏览器缓存方案:关于思路,细节,ServiceWorker,以及HTTP/2
「面试题」简述浏览器缓存是如何控制的

关于网络协议中HTTP协议
HTTP 缓存
浅谈HTTP缓存
一文读懂http缓存(超详细)
http缓存详解( 直接看图,超易懂🤗 )

浏览器数据库 IndexedDB 入门教程

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
前端性能优化实践# 知识体系与小册格局 ## 写给读者 提起性能优化,大家现在脑海里第一时间会映射出什么内容呢? 可能是类似[“雅虎军规”](https://developer.yahoo.com/performance/rules.html?guccounter=1)和[《高性能 JavaScript》](https://book.douban.com/subject/5362856/)这样历久弥香的经典之作,也可能是搜索引擎聚合给你的一篇又一篇以性能优化为主题的个人或团队实践而来的“私货”。至少当我确定自己的研发方向、并接到第一个性能优化任务时,我做的第一件事是向搜索引擎求助,第二件事是买书,然后开始了摸着石头过河,前后花费了大量的时间和精力。我深感性能优化实在是前端知识树中特别的一环——当你需要学习前端框架时,文档和源码几乎可以告诉你所有问题的答案,当你需要学习 Git 时,你也可以找到放之四海皆准的实践方案。但性能优化却不一样,它好像只能是一个摸索的过程。 这个摸索的过程是痛苦的、漫长的,也是紧要的。因为在如今的互联网环境下,一个前端团队如果只把性能优化这个任务写在纸上,而不投入实践,它将缺失最基本的竞争力。 笔者写这本小册,是希望通过短短十数个章节的讲解,尽可能降低一些大家学习性能优化的成本。 一方面,这本小册为没有接触过性能优化的新同学建立起一个正确的前端性能优化的“世界观”,知道性能优化是什么、为什么、怎么做,从而使性能优化这件事情有迹可循,有路可走。这样在面试现场被问到性能优化层面的问题时,能够做到滔滔不绝、言之有物,而非像背书一样罗列干巴巴的知识点,最终淹没在茫茫的求职大军中。另一方面,小册可以为在职的工程师们提供一线团队已经实践过的“方法论”,知道什么场景下该做什么事情,最终在脑海中留下一张涵盖核心原理和实践的、可随时查阅并且高度可扩展的性能优化思路索引表。然后在今后的开发生活中可以去践行它,更进一步去挖掘它。把性能优化变作你前端工程师生涯的一门必修课,进而演化为自己研发方面的核心竞争力。 同时,相信大家可以明确这样一个学习观念:任何技术的掌握,都离不开一定比例的理论基础和实际操作的支撑。 具体到前端性能优化这件事情上,我认为它是 20% 的理论,加上至少 80% 的实践,甚至很多理论本身也都是我们在具体的业务场景中实践出来的。所以希望大家阅读本小册时,能够读到一些“书本之外的东西”——最好是一边读一边回忆自己既有的开发经历,尝试去留意哪些知识是已知的,哪些是未知的。 这样读完之后,就可以有的放矢地把这些知识转换为自己的项目实践——前端技术日新月异,性能方案永远都在更迭,所以一定要形成自己的学习思路。 建议每一位读者都带着“学了就要用”的心态去读这本小册。如果阅读结束,能够为你带来哪怕一个小小的开发习惯或者优化观念上的改变,这数小时的阅读时间就算没有白费。 ## 知识体系: 从一道面试题说起 在展开性能优化的话题之前,我想先抛出一个老生常谈的面试问题: > 从输入 URL 到页面加载完成,发生了什么? 这个问题非常重要,因为我们后续的内容都将以这个问题的答案为骨架展开。我希望正在阅读这本小册的各位可以在心里琢磨一下这个问题——无须你调动太多计算机的专业知识,只需要你用最快的速度在脑海中架构起这个抽象的过程——我们接下来所有的工作,就是围绕这个过程来做文章。 我们现在站在性能优化的角度,一起简单地复习一遍这个经典的过程:首先我们需要通过 DNS(域名解析系统)将 URL 解析为对应的 IP 地址,然后与这个 IP 地址确定的那台服务器建立起 TCP 网络连接,随后我们向服务端抛出我们的 HTTP 请求,服务端处理完我们的请求之后,把目标数据放在 HTTP 响应里返回给客户端,拿到响应数据的浏览器就可以开始走一个渲染的流程。渲染完毕,页面便呈现给了用户,并时刻等待响应用户的操作(如下图所示)。 ![](https://user-gold-cdn.xitu.io/2018/10/18/16685737b823244c?w=489&h=329&f=png&s=19023) 我们将这个过程切分为如下的过程片段: 1. DNS 解析 2. TCP 连接 3. HTTP 请求抛出 4. 服务端处理请求,HTTP 响应返回 5. 浏览器拿到响应数据,解析响应内容,把解析的结果展示给用户 大家谨记,我们任何一个用户端的产品,都需要把这 5 个过程滴水不漏地考虑到自己的性能优化方案内、反复权衡,从而打磨出用户满意的速度。 ## 从原理到实践:各个击破 我们接下来要做的事情,就是针对这五个过程进行分解,各个提问,各个击破。 具体来说,DNS 解析花时间,能不能尽量减少解析次数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值