目标
优化的是H5(static),请求走静态资源文件。
将静态资源的请求路由到CDN
静态请求CDN
结构图
DNS用CNAME解析源站
回源缓存设置
cache control响应头
Request Headers:
例:
GET / HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: Hm_lvt_512065947708a980c982b4401d14c2f5=1551084094; SESSION=OGQzOGIzMGEtZGYyNy00MjQ4LWI1ZGYtMjc2OTAxYjJmNjEz
###cache control有几种取值:
private:客户端可以缓存(请求发起的浏览器才可以缓存)
public:客户端和代理服务器(反向或正向代理)都可以缓存
max-age=xxx:缓存的内容将在xxx秒之后失效
也就是说我们对应缓存的内容,从收到服务端的这个max-age返回数据开始,存储xxx秒后这个请求就失效,客户端必须往对应的服务端上面再次发起请求,用来验证和结束对应的请求体
no-cache:强制向服务端再验证一次(会将对应的缓存存储在客户端,但是在下次用的时候要向服务端验证一次这个缓存到底是能用还是不能用,no-store是压根不存)
no-store:不缓存请求的任何返回内容
怎么选择HTTP cache control头?
有效性判断
- ETag:资源唯一标识
- If-None-Match:客户端发送的匹配ETag标识符
- Last-modified:资源最后被修改时间
- If-Modified-Since:客户端发送的匹配资源最后修改时间的标识符
补充:
ETag:
一般是将请求的资源做一个MD5或者类似hash操作,生成一个ETag的唯一标识,服务端在第一次返回内容中加上这个ETag的唯一标识,一起返回给浏览器,浏览器会存储下来这个ETag;下一次请求的时候,所谓的有效性判断,是浏览器将之前缓存下来内容的ETag的值一起带到服务器上,用来验证说它不发送具体的响应,而是发送一个对应的HTTP请求并且带上这个ETag的值,服务端会将这个ETag的值和我本地的文件ETag内容做比较,若比较是一致的,就返回304 not-modified,告诉客户端说服务端这个内容是有效的,直接使用浏览器里的缓存即可
若If-Modified-Since的值早于Last-modified的值,证明是无效的;若晚于Last-modified的值,则是有效的,说明这段时间资源没有被修改过。
用户请求浏览器资源的网站路径
浏览器三种刷新方式
- 回车刷新或者a链接(get请求跳转):看cache-control对应的max-age是否仍然有效,有效则直接从cache取对应的数据,若cache-control中为no-cache,则进入缓存协商逻辑
- F5刷新(Windows)或者command+R(macOS)刷新:去掉cache-control中的max-age或者直接设置max-age为0,然后进入缓存协商逻辑
- ctrl+F5或commond+shift+R刷新:去掉cache-control和协商头,强制刷新 (强制从服务端拿内容)
对应的协商机制:
比较Last-modified和ETag到服务端,若服务端判断没变化则304不返回数据,否则200返回数据
CDN自定义缓存策略
- 可自定义目录过期时间
- 可自定义后缀名过期时间
- 可自定义对应权重
- 可通过界面或api强制cdn对应目录刷新(不一定保证成功)
阿里云CDN配置
静态资源部署策略(1)
- css,js,img等元素使用带版本号部署,例如
a.js?=v1.0
不便利,且维护困难 - css,js,img等元素使用带摘要(hash获得)部署,例如a
.js?=45edw
,存在先部署html还是先部署资源的覆盖问题 - css,js,img等元素使用带摘要做文件名部署,例如
45edw.js
,新老版本并存且可回滚,资源部署完后再部署HTML
采用第三种
静态资源部署策略(2)
对静态资源保持生命周期内不会变,max-age可设置很长,无视失效更新周期
html文件设置no-cache或较短max-age,以便更新
html文件仍然设置较长的max-age,依靠动态的获取版本号请求发送到后端,异步下载最新的版本号的html展示渲染在前端
将html文件缓存。html每次都能展示缓存离的内容,没有问题,但是html文件里面每次在启动的时候有一个很小很小的
ajax
请求头,ajax请求做的事情就是带着本地的html版本号去我的服务端调用一个动态的接口,这个动态的接口比较ajax中html版本号和后端的版本号是否是最新的;如果是的话,对应的html渲染到前端即可;如果不是,就需要在后端从新下载最新版本号的html(异步更新策略)
第三种方式是最好的,但是一般第二种也足够使用
静态资源部署策略(3)
上面讨论的都是静态资源文件
- 动态请求可以静态化成json资源推送到cdn上
- 依靠异步请求获取后端节点对应资源状态做紧急下架处理
- 可通过跑批紧急推送cdn内容以使其下架等操作
强推失效
全页面静态化
- html,css,js静态资源cdn化
- js,ajax动态请求cdn化
- 全页面静态化
定义
在服务端完成html,css,甚至js的load;并且渲染成纯html文件后直接以静态资源的方式部署到cdn上
phantomjs
可以理解为无头浏览器,可以借助其模拟webkit js的执行
- 演示样例
js:
var page = require('webpage').create();
page.open('http://www.baidu.com', function() {
setTimeout(function() {
page.render('baidu.png');
phantom.exit();
}, 200);
});
- 运行:
phantomjs spiderbaidu.js
- 结果:
phantomjs应用
- 修改需要全页面静态化的实现,采用
initView
和hasInit
方式防止多次初始化 - 编写对应轮询生成内容方式
- 将全静态化页面生成后推送到CDN
1.在/usr/local/Caskroom/phantomjs/2.1.1/phantomjs-2.1.1-macosx/js/
下创建getitem.js
var page = require("webpage").create();
var fs = require("fs");
page.open("http://localhost/resources/getitem.html?id=6",function(status){
console.log("status= "+status);
fs.write("getitem.html",page.content,"w");
phantom.exit();
});
2.执行
xuxinghua@xxhdemac:/usr/local/Caskroom/phantomjs/2.1.1/phantomjs-2.1.1-macosx/js$ phantomjs getitem.js
status= success
成功后会在当前目录生成getitem.html
xuxinghua@xxhdemac:/usr/local/Caskroom/phantomjs/2.1.1/phantomjs-2.1.1-macosx/js$ ls
getitem.html getitem.js