HTTP 缓存机制
缓存分类
HTTP 缓存模型中,如果请求成功会有三种情况
- 200 from cache: 直接从本地缓存中获取响应,最快速,最省流量,因为根本没有向服务器发送请求。
- 304 Not Modified: 协商缓存,浏览器在本地没有命中的情况下请求头中发送一定的校验数据到服务端,如果服务端数据没有改变,浏览器从本地缓存响应,返回 304。
快速,发送的数据很少,支付你会一些基本的响应头信息,数据量很小,不发送实际响应体。 - 200 OK: 以上俩种缓存全都失败,服务器返回完整响应。没有用到缓存,相对最慢。
本地缓存(200 from cache)
浏览器认为本地缓存可以使用,不会去请求服务端
相关 Header如下:
Pragma
:HTTP1.0
时代的遗留产物,该字段被设置为no-cache
时,会告知浏览器禁用本地缓存,即每次都想服务器发送请求。Expires
:HTTP1.0
时代用来启动本地缓存的字段,expires
值对应一个形如Thu, 31 Dec 2037 23:55:55 GMT
的格林威治时间,告诉浏览器缓存实现的时刻,如果还没到该时刻,标明缓存有效,无需发送请求。Cache-Control
: 浏览器与服务器的时间无法保持一致,如果时间差距大,就会影响缓存结果。HTTP1.1
针对Expires
时间不一致的解决方案,运用Cache-Control
告知浏览器缓存过期的时间间隔而不是时刻,即使具体时间不一致,也不影响缓存的管理。常见的设置如:
no-store
: 禁止浏览器缓存响应
no-cache
: 不允许直接使用本地缓存,先发起请求和服务器协商
max-age=delta-seconds
: 告知浏览器该响应本地缓存有效的最长期限,以秒为单位
优先级:Prama > Cache-Control > Expires
协商缓存(304 Not Modified)
当浏览器没有命中本地缓存,如本地缓存过期或者响应中声明不允许直接使用本地缓存,那么浏览器肯定会发起服务端请求。
服务端会验证数据是否修改,如果没有通知浏览器使用本地缓存
相关 Header如下:
Last-Modified
: 通知浏览器资源的最后修改时间
格式:Wed, 31 Oct 2018 17:58:45 GMT
If-Modified-Since
: 得到资源的最后修改时间后,会将这个信息通过If-Modified-Since
提交到服务器做检查,如果没有修改,返回 304 状态码
格式:Wed, 31 Oct 2018 17:58:45 GMT
ETag
:HTTP1.1
推出,文件的指纹标识符,如果文件内容修改,指纹会改变
格式:"E58B212330002C53928B1EC0857DD370"
If-None-Match
: 本地缓存失效,会携带此值去请求服务端,服务端判断该资源是否改变,如果没有改变,直接使用本地缓存,返回 304
格式:"E58B212330002C53928B1EC0857DD370"
缓存策略的选择
建议使用本地缓存
:
- 不变的图像,如 Logo,图标等
- js、css 静态文件
- 可下载的内容,媒体文件
建议使用协商缓存
:
- HTML 文件
- 经常替换的图片
- 经常修改的 js、css 文件
- js、css 文件的加载可以加入文件的签名来拒绝缓存
index.css?签名
index.签名.js
不建议使用缓存
:
- 用户隐私等敏感数据
- 经常改变的 api 数据接口
//php 代码测试下
<?php
$since = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
$lifetime = 10;
if (strtotime($since) + $lifetime > time())
{
header('HTTP/1.1 304 Not Modified');
exit;
}
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT');
echo time();
Nginx 配置缓存策略
本地缓存配置
add_header 指令:添加状态码为 2XX 和 3XX 的响应头信息
add_header name value [always];
可以设置 Pragma/Expires/Cache-Control,可以继承
- exprires 指令:通知浏览器过期时长
expires time;
为负值时表示 Cache-Control:no-cache;
当为正或者 0 时,就表示 Cache-Control:max-age=指定的时间;
当为 max 时,会把 Expires 设置为 “Thu, 31 Dec 2037 23:55:55 GMT”, Cache-Control 设置到 10 年;
协商缓存相关配置
Etag 指令:指定签名
etag on | off; 默认是 on
前端代码和资源的压缩
优势:让资源文件更小,加快文件在网络中的传输,让网页更快的展现,降低带宽和流量开销
压缩方式:JS、CSS、图片、HTML 代码的压缩;Gzip 压缩
-
JavaScript 代码压缩
JavaScript 压缩的原理一般是去掉多余的空格和回车、替 名、简化一些代码写法等。
常用的压缩工具:UglifyJS、YUI Compressor、Closure Compiler.
UglifyJS: 压缩、语法检查、美化代码、代码缩减、转化
YUI Compressor: 来自 Yahoo、只有压缩功能
Closure Complier: 来自 Google、功能和 UglifyJS 类似,压缩的方式不一样 -
CSS 代码压缩
常用的压缩工具:YUI Compressor、CSS Compressor
CSS Compressor: 压缩时可以选择模式 -
HTML 代码压缩
不建议使用代码压缩,有时会破坏代码结构,可以使用 Gzip 压缩,也可以使用 htmlcompressor 工具,不过转换后一定要检查代码结构。 -
图片压缩
除了代码的压缩外,有时对图片的压缩也是很有必要,一般情况下图片在 web 系统的比重都比较大。
压缩工具:tinypng、JpegMini、ImageOptim -
Gzip压缩
配置Nginx
服务
gzip on|off; #是否开启gzip
gzip_buffers 32 4K | 16 8K #缓冲(在内存中缓冲几块?每块多大)
gzip_comp_level [1-9] #推荐6 压缩级别(级别越高,压得越小,越浪费CPU计算资源)
gzip_disable #正则匹配UA 什么样的 Uri 不进行 gzip
gzip_min_length 200 #开始压缩的最小长度
gzip_http_version 1.0 | 1.1 #开始压缩的 http 协议版本
gzip_proxied #设置请求者代理服务器,该如何缓存内容
gzip_types text/plain application/xml # 对哪些类型额文件用压缩 如 txt,xml,html,css
gzip_vary on|off #是否传输gzip压缩标志
查看内容是否使用了 gzip
: 看响应头里会有 Content-Encoding: gzip
以上资源均来自网络,只为记录~