前端性能优化 - 设置缓存

121 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

前言

前端性能优化系列,记录在优化过程中的问题,可能有十万个为什么,待以后懂了再记录,毕竟太菜啥都不懂。

而且部分优化(设置缓存、gzip压缩、使用CDN加速服务)非开发人员来控制,而是网站服务器管理员的职责。

一、缓存分为两类

  • 强缓存:不向服务器发送请求,直接使用客户端本地缓存数据
  • 协商缓存:向服务器发送请求,由服务器判断请求文件是否发生改变。若未发生改变,则返回304状态码,通知客户端直接使用本地缓存;如果发生改变,则直接返回请求文件。

参见下图

200(from memory cache)和304(Not Modified)

在这里插入图片描述

1、强缓存

强缓存,又有Expires和Cache-Control之分。

差别如下:

Expires:(该时间是一个绝对时间)

其值直接是绝对时间

Cache-Control:(该时间是一个相对时间)

值为:

  • max-age:即最大有效时间,在上面的例子中我们可以看到
  • no-cache:表示没有缓存,即告诉浏览器该资源并没有设置缓存
  • s-maxage:同max-age,但是仅用于共享缓存,如CDN缓存
  • public:多用户共享缓存,默认设置
  • private:不能够多用户共享,HTTP认证之后,字段会自动转换成private。

比如:Cache-Control: max-age=2592000

缺点

如果上线的一个图片设置的强制缓存,图片更新了部署到服务器,但是用户那边始终读到的缓存里的原图,你没法要求用户清空浏览器缓存。

当然了,你可以修改图片的名字解决这个问题。

2、协商缓存

协商缓存,又有Last-Modified和If-Modified-Since、Etag和If-None-Match。

差别如下:

Last-Modified和If-Modified-Since

服务器会将If-Modified-Since的值与Last-Modified字段进行对比,如果相等,则表示未修改,响应304;反之,则表示修改了,响应200状态码,返回数据。

缺点

如果资源更新的速度是秒以下单位,那么该缓存是不能被使用的,因为它的时间单位最低是秒。

如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用。

Etag和If-None-Match

服务器存储着文件的Etag字段,可以在与每次客户端传送If-no-match的字段进行比较,如果相等,则表示未修改,响应304;反之,则表示已修改,响应200状态码,返回数据。

3、缓存的优先级

  • 强缓存优先级 > 对比缓存优先级
  • cache-control优先级 > expires优先级
  • ETag优先级 > Last-Modified优先级

二、对比初次加载与从缓存中加载

接下来对比一下,一个资源的初次加载和从缓存中加载,如图所示:

在这里插入图片描述

此处注意,虽然size=178B<3.0KB,但是time=321ms>291ms。

这……

我猜

  • 1、因为本地部署,机器性能好、网络环境好,所以直接读取或缓存读取差别不大,时间有浮动保持在300ms左右。
  • 2、因为文件大小本身很小,导致直接读取或缓存读取差别不大。
  • 3、因为从缓存中读取经历了两步,多了比较ETag的时间。

问题来了

很明显从缓存加载速度竟然还比较慢,但是这里是通过协商缓存进行了比较,如果直接强制缓存,是不是更快呢?

我也不知道怎么设置Expires,哎……满脑子疑问如下:

  • 1、本地,ETag在哪里配置??似乎默认都有
  • 2、本地,Expires在哪里配置??

webpack.base.conf.js里配置加上ico并没有什么差别

{
        test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
  • 3、服务器,nginx上配置ETag?配置了ETag: off但并没有什么作用?
  • 4、服务器,nginx上配置Expires?

.svg和.glb明明没有配置默认有Expires,ico配置了似乎不起作用。

配置加上了Cache-Control "public",request确实加上了public,但是response里Cache-Control 始终是no-cache。

换火狐浏览器看,虽然写着请求200 OK,且消息头有no-cache,但仍然显示已缓存如下图,费解。

在这里插入图片描述

# Media: images, icons, video, audio, HTC
#location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
#  root   E:/svn-workspace/pro/dist/;
#  expires 1M;
#  access_log off;
#  add_header Cache-Control "public";
#}
# CSS and Javascript
#location ~* \.(?:css|js)$ {
#  root   E:/svn-workspace/pro/dist/;
#  expires 1y;
#  access_log off;
#}

总而言之

缓存就默认吧,似乎浏览器自己有一套比较好的设置,只需自己调整这些资源的Expires时间。

三、关于ico的缓存问题

服务器端nginx.conf配置中

location ~*\.(js|css|png|jpg|jpeg|gif|ico)$ {
   root   E:/svn-workspace/pro/dist/;
   expires 30d;
}

确实对ico配置了过期时间30天,然而查看资源请求时发现:

  • 1、直接输入地址访问是没有favicon.ico资源请求的
  • 2、刷新时有favicon.ico资源请求,虽然加了过期时间expires30天没问题,但是请求消息头中有个no-cache不知道在哪配置的啊,同时查看其它png|jpg资源都不存在这个no-cache,为什么呢?

在这里插入图片描述

四、参考文档

juejin.im/post/5b3da0… kailian.github.io/2016/07/17/…