Skip to content

Latest commit

 

History

History
138 lines (81 loc) · 7.84 KB

File metadata and controls

138 lines (81 loc) · 7.84 KB

1. 页面性能优化

1.1. 提问:提升页面性能的方法有哪些?

  1. 资源压缩合并,减少 http 请求

  2. 非核心代码异步加载 --> 异步加载的方式 --> 异步加载的区别

  3. 利用浏览器缓存 --> 缓存的分类 --> 缓存的原理

    缓存是所有性能优化的方式中最重要的一步,这个一定要答好。

    别说 local storage 和 session storage。浏览器缓存和存储根本不是一回事。

  4. 使用 CDN

    浏览器第一次打开页面时,缓存是起不了作用的。CDN 这一条,一定要说出来。

  5. DNS 预解析

1.1.1. 资源压缩合并,减少 HTTP 请求

  • 合并图片(css sprites)、CSS 和 JS 文件合并、CSS 和 JS 文件压缩
  • 图片较多的页面也可以使用 lazyLoad 等技术进行优化。
  • 精灵图等

1.1.2. 非核心代码异步加载

1.1.2.1. 异步加载的方式

  1. 动态脚本加载 用document.createElement等动态创建节点
  2. defer 在加载 js 的时候在 script 标签上加上这个属性就能完成异步加载。
  3. async 在加载 js 的时候在 script 标签上加上这个属性就能完成异步加载。

1.1.2.2. 异步加载的区别

  1. defer 是在 HTML 解析完之后才会执行,如果是多个,按照加载的顺序依次执行
  2. async 是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关

1.1.3. 利用浏览器缓存

缓存:资源文件(比如图片)在本地的硬盘里存在的备份,浏览器下次请求的时候,可能直接从本地磁盘里读取,而不会重新请求图片的 url。

缓存分为:

  • 强缓存
  • 协商缓存

1.1.3.1. 强缓存

强缓存:用请求服务器,直接使用本地的缓存。 强缓存是利用 http 响应头中的ExpiresCache-Control实现的。 浏览器第一次请求一个资源时,服务器在返回该资源的同时,会把上面这两个属性放在 response header 中。

注意:这两个 response header 属性可以只启用一个,也可以同时启用。当 response header 中,Expires 和 Cache-Control 同时存在时,Cache-Control 的优先级高于 Expires

  1. Expires:服务器返回的绝对时间

    是较老的强缓存管理 response header。浏览器再次请求这个资源时,先从缓存中寻找,找到这个资源后,拿出它的 Expires 跟当前的请求时间比较,如果请求时间在 Expires 的时间之前,就能命中缓存,否则就不行。

    如果缓存没有命中,浏览器直接从服务器请求资源时,Expires Header 在重新请求的时候会被更新。

    缺点

    由于 Expires 是服务器返回的一个绝对时间,存在的问题是:服务器的事件和客户端的事件可能不一致。在服务器时间与客户端时间相差较大时,缓存管理容易出现问题,比如随意修改客户端时间,就能影响缓存命中的结果。所以,在 http1.1 中,提出了一个新的 response header,就是 Cache-Control。

  2. Cache-Control:服务器返回的相对时间

    http1.1 中新增的 response header。浏览器第一次请求资源之后,在接下来的相对时间之内,都可以利用本地缓存。超出这个时间之后,则不能命中缓存。重新请求时,Cache-Control 会被更新。

1.1.3.2. 协商缓存

协商缓存:浏览器发现本地有资源的副本,但是不太确定要不要使用,于是去问问服务器。

当浏览器对某个资源的请求没有命中强缓存(也就是说超出时间了),就会发一个请求到服务器,验证协商缓存是否命中。

协商缓存是利用的是两对 Header:

第一对:Last-ModifiedIf-Modified-Since

第二对:ETagIf-None-Match

ETag(Entity Tag):被请求变量的实体值。

  1. Last-ModifiedIf-Modified-Since。过程如下:

    (1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上 Last-Modified 这个 response header,这个 header 表示这该资源在服务器上的最后修改时间; (2)浏览器再次请求这个资源时,会加上 If-Modified-Since 这个 request header,这个 header 的值就是上一次返回的 Last-Modified 的值; (3)服务器收到第二次请求时,会比对浏览器传过来的 If-Modified-Since 和资源在服务器上的最后修改时间 Last-Modified,判断资源是否有变化。如果没有变化则返回 304 Not Modified,但不返回资源内容(此时,服务器不会返回 Last-Modified 这个 response header);如果有变化,就正常返回资源内容(继续重复整个流程)。这是服务器返回 304 时的 response header; (4)浏览器如果收到 304 的响应,就会从缓存中加载资源。

    缺点Last-ModifiedIf-Modified-Since 一般来说都是非常可靠的,但面临的问题是:

    • 服务器上的资源变化了,但是最后的修改时间却没有变化。

    • 如果服务器端在一秒内修改文件两次,但产生的 Last-Modified 却只有一个值。

    这一对 header 就无法解决这种情况。于是,下面这一对 header 出场了。

  2. ETagIf-None-Match。过程如下:

    (1)浏览器第一次请求一个资源,服务器在返回这个资源的同时,会加上 ETag 这个 response header,这个 header 是服务器根据当前请求的资源生成的唯一标识。这个唯一标识是一个字符串,只要资源有变化这个串就不同,跟最后修改时间无关,所以也就很好地补充了 Last-Modified 的不足; (2)浏览器再次请求这个资源时,会加上 If-None-Match 这个 request header,这个 header 的值就是上一次返回的 ETag 的值; (3)服务器第二次请求时,会对比浏览器传过来的 If-None-Match 和服务器重新生成的一个新的 ETag,判断资源是否有变化。如果没有变化则返回 304 Not Modified,但不返回资源内容(此时,由于 ETag 重新生成过,response header 中还会把这个 ETag 返回,即使这个 ETag 并无变化)。如果有变化,就正常返回资源内容(继续重复整个流程)。这是服务器返回 304 时的 response header: (4)浏览器如果收到 304 的响应,就会从缓存中加载资源。

1.1.4. 使用 CDN

怎么最快地让用户请求资源。一方面是让资源在传输的过程中变小,另外就是 CDN。

要注意,浏览器第一次打开页面的时候,浏览器缓存是起不了作任何用的,使用 CDN,效果就很明显。

1.1.5. 预解析 DNS

通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。

第一步:打开或关闭 DNS 预解析

你可以通过在服务器端发送 X-DNS-Prefetch-Control 报头。或是在文档中使用值为 http-equiv 的 meta 标签:

<meta http-equiv="x-dns-prefetch-control" content="on" />

需要说明的是,在一些高级浏览器中,页面中所有的超链接(<a>标签),默认打开了 DNS 预解析。但是,如果页面中采用的 https 协议,很多浏览器是默认关闭了超链接的 DNS 预解析。如果加了上面这行代码,则表明强制打开浏览器的预解析。(如果你能在面试中把这句话说出来,则一定是你出彩的地方)

第二步:对指定的域名进行 DNS 预解析

如果我们将来可能从 smyhvae.com 获取图片或音频资源,那么可以在文档顶部的 标签中加入以下内容:

<link rel="dns-prefetch" href="http://www.smyhvae.com/" />

当我们从该 URL 请求一个资源时,就不再需要等待 DNS 解析的过程。该技术对使用第三方资源特别有用。