最新的 Google Android 用户行为分析中,得到以下几个数据
- – 如果站点加载时间超过3s,53%的用户会放弃等待
- – 页面加载后,用户期望的平滑的体验,过渡动画和快速响应,并不喜欢不断的页面跳转
- – 84%的移动端浏览器已经支持PWA
- – 50%的用户启用了通知服务
PWA(Progressive Web App)给用户原生APP的体验,其实不难发现PWA核心就是建立在离线缓存和后台数据交互基础上构建的崭新的Web app,使其具备了Native App的部分特性。那么从缓存开始我们一步步在技术上组装PWA服务。为了使本篇教程更多的朋友能触类旁通,我们技术栈尽量从浅入深。
前端工程化的发展,意味着产品的重点从原来的功能体验,越来越升级到用户体验。从早期的代码压缩,到减少http请求,异步加载,通过CDN的内容分发,缓存等技术的综合应用,从几十秒到几十毫秒的优化而费尽心思。这些应用体验只是为了“秒开”页面。
为了达到秒开的效果,必然要在客户端做持久的离线缓存,HTML5的离线缓存就是最主要的特性之一,2014年W3C就开始提倡ServiceWorker,为了更好的理解ServiceWorker我们就要从离线缓存控制环节一步步揭开它的面纱,先让我们回顾一下HTML5控制离线缓存的各种方式吧。
随着HTTP1.1的协议最早使用的缓存机制,通过HTTP头来控制用户代理(浏览器)是否把头对应的文件进行缓存,缓存多长时间。通过HTTP RESPONSE HEADERS属性来控制页面加载的元素缓存。
Cache-Control 服务端缓存控制来控制元素的加载
课程中我们使用Chrome浏览器,
1. 打开 [baidu.com](https://baidu.com)
2. 打开开发者工具 Ctrl+Shift+i
3. 点击顶部NetWork
4. 选择下面的加载列表
可以看到页面加载的所有URI资源的属性,当然我们现在更关注的是缓存,那么请注意右侧的Cache-Control的属性:
Cache-Control 属性告诉用户代理缓存机制是否可以缓存及哪种类型。他包含以下值:
– public 所有内容都将被缓存(客户端和代理服务器都可缓存)
– private 内容只缓存到私有缓存中(仅客户端可以缓存,浏览器不可缓存)
– no-cache 不缓存
– no-store 所有内容都不会被缓存
– must-revalidation/proxy-revalidation 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
– max-age=xxx (xxx is numeric) 缓存的内容将在 xxx 秒后失效
- `Cache-Control:max-age=315160000 //10年后过期`
我们可以发现百度首页把常用的资源,都进行了缓存,我们通过选择左侧的属性列表也可以看到几个不缓存的案例。当然Cache-Control属性不止这些,推荐大家阅读以下文档更多的理解Cache-Control
1、百度百科:[https://baike.baidu.com/item/Cache-control/1885913?fr=aladdin](https://baike.baidu.com/item/Cache-control/1885913?fr=aladdin)
2、MDN: [https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control)
扩展
- `strict-transport-security: max-age=31536000`
我们如果查看Google或者Facebook等国外站点不难发现headers头部没有cache-control属性,而变成了strict-transport-security。其实这也是缓存的一种机制,更有利https缓存介入,国内从去年刚刚才大量普及https,但是用户习惯输入http,服务器一般直接做了强制跳转https资源,这样存在中间人攻击潜在威胁,跳转过程可能被恶意网站利用来直接接触用户信息,而不是原来的加密信息。网站通过HTTP Strict Transport Security通知浏览器,这个资源禁止使用HTTP方式加载,浏览器应该自动把所有尝试使用HTTP的请求自动替换为HTTPS请求。
为了更好的兼容性考虑,如建议使用:
- `cache-control: public, max-age=31536000`
当然在经常修改的内容上我们也可以加入这样的方式进行缓存
- Cache-Control: must-revalidate, max-age=60
- //一分钟内不需要重新认证,超过一分钟就需要重新认证
但使用这种方式一定要注意,缓存时间是服务器时间,并不是用户代理(浏览器)时间。所以如果多个资源都使用了重新加载,我们无法保证在同一时间某个资源是没有被加载的。多个资源间不匹配。页面崩塌。当然我们继续学习下去,后续我们学习serviceWorker就可以杜绝这个问题出现。
当下多数公司网站的图片,js,css等文件的缓存会选择Nginx的web缓存服务。Nginx的Web缓存服务主要由proxy_cache相关指令集和fastcgi_cache相关指令集构成。
1. proxy_cache相关指令集用于反向代理时,对后端内容源服务器进行缓存.Nginx的proxy_cache缓存功能,十分稳定。
2. fastcgi相关指令集主要用于对FastCGI的动态程序进行缓存.两者功能基本一样.
proxy_cache相关指令集
1. proxy_cache
- proxy_cache zone_name
- # 从一个指定的地址获取内容,然后缓存。当下次访问时,nginx会自动判断有没有缓存文件?如果有的话缓存文件是不是已经过期.
2. proxy_cache_path
- proxy_cache_path /www/nginx/proxy_cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=10g ;
- # path 表示存放目录
- # levels 表示指定该缓存空间有两层hash目录,第一层目录为1个字母,第二层目录为2个字母,
- # 保存的文件名会类似/www/nginx/proxy_cache/a/11/**** ;
- # keys_zone参数用来为这个缓存区起名.
- # 500m 指内存缓存空间大小为 500MB
- # inactive的1d指如果缓存数据在1天内没有被访问(支持单位m/y/d/w)将被删除。相当于expires过期时间的配置;
- # max_size的10g是指硬盘缓存空间为10G
3. proxy_cache_methods
- proxy_cache_methods GET POST HEAD DELETE;
- # 用于设置缓存哪些HTTP方法,默认缓存HTTP GET/HEAD方法,不缓存HTTP POST 方法,通过设置名称缓存不同方法
4. proxy_cache_min_uses
- proxy_cache_min_uses 1000
- # 设置缓存的最小使用次数,默认值为1
5. proxy_cache_valid
- proxy_cache_valid 200 302 10m ;
- proxy_cache_valid 404 1m ;
- 设置200,302状态的URL缓存10分钟,404状态的URL缓存1分钟.
6. proxy_cache_key
- proxy_cache_key $uri ;
- 定义缓存唯一key,通过唯一key来进行HASH存取
当然我们最后一个问题,这个Headers是怎么配置的,如果你是前端工程师,你一定会选用Nginx+node的反向代理和负载均衡的方式处理你的业务。一个简单KOA2的header的配置吧,只需要set一下就ok了,你可以通过nginx的反向代理控制服务器缓存。甚至我们会把需要缓存的资源独立一个Koa进行处理,这样能发挥更多CDN的能力。
- const Koa = require('koa');
- const app = new Koa();
- app.use(async ctx => {
- ctx.set('Cache-Control', "public, max-age=31536000")
- ctx.response.type = "text"
- ctx.response.body = "Hello World"
- });
- app.listen(3000);
转载: https://wosclass.com/2019/03/07/%E7%AC%AC%E4%BA%8C%E7%AB%A0-%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%A6%BB%E7%BA%BF%E7%BC%93%E5%AD%98%E6%8A%80%E6%9C%AF/