持续创作,加速成长!这是我参与「掘金日新计划 · 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,为什么呢?