解析Web缓存及其最佳实践
关注“前端学苑” ,坚持每天进步一点点
「~web缓存解析~」
缓存一直以来都是用来提高性能的一项必不可少的技术,利用这项技术可以很好地提高web的性能。缓存可以很有效地降低网络的时延,同时也会减少大量请求对于服务器的压力。
一、为什么要用缓存
一般针对静态资源如CSS,JS,图片等使用缓存,原因如下:
1) 请求更快:通过将内容缓存在本地浏览器或距离最近的缓存服务器(如CDN),在不影响网站交互的前提下可以大大加快网站加载速度。
2) 节省带宽:对于已缓存的文件,可以减少请求带宽甚至无需请求网络。
3) 降低服务器压力:在大量用户并发请求的情况下,服务器的性能受到限制,此时将一些静态资源放置在网络的多个节点,可以起到均衡负载的作用,降低服务器的压力。
「~前端缓存导图~」
二、前端缓存技术方案,主要分为http缓存和浏览器缓存
HTML Meta标签控制缓存(非HTTP协议定义)
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代码的作用是告诉浏览器当前页面不被缓存,每次访问都需要去服务器拉取。
1、HTTP缓存
HTTP头信息控制缓存是通过Expires(强缓存)、Cache-control(强缓存)、Last-Modified/If-Modified-Since(协商缓存)、Etag/If-None-Match(协商缓存)实现。
强缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。
1)Expires
Expires(http1.0的规范)表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回,用GMT格式的字符串表示。
例如:当Expires: Wed, 22 Oct 2018 08:41:00 GMT时表示资源会在 Wed, 22 Oct 2018 08:41:00 GMT 后过期,需要再次请求。
读取缓存数据条件:缓存过期时间(服务器的)< 当前时间(客户端的)
2)Cache-Control
Cathe-Control(http1.1规范)描述的是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,所以相比较Expires,Cache-Control的缓存管理更有效,安全一些。
例如:当Cache-Control:max-age=300时,则代表在这个请求正确返回时间(浏览器也会记录下来)的5分钟内再次加载资源,就会命中强缓存。缓存5分钟后就过期,需要重新请求。
读取缓存数据条件:上次缓存时间(客户端的)+max-age < 当前时间(客户端的)
说明:两者同时存在的话,Cache-Control优先级高于Expires;
协商缓存
协商缓存:会发请求到服务器。控制协商缓存可以通过设置两种 HTTP Header 字段实现:Last-Modify/If-Modified-Since 和 Etag/If-None-Match,这两个字段是成对使用的。
1)Last-Modify/If-Modified-Since
1) 浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;
2) 浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;
3) 服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,
4) 如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。
2)ETag和If-None-Match
1) Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。
2) 浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,
3) 服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
4) 如果服务器发现ETag匹配不上,那么直接以常规GET 200 形式将新的资源(当然也包括了新的ETag)发给客户端;
5) 如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
使用缓存流程,从浏览器请求到展示资源的过程:
浏览器缓存机制,其实主要就是HTTP协议定义的缓存机制(如:Expires;Cache-control等)。
2、浏览器缓存
1)存储 (storage)
简单的缓存方式有sessionStorage、localStorage和cookie。
共同点:都是保存在浏览器端,且同源的。
区别:
数据传输方面:
在每个http请求中都会附加cookie信息,cookie中的信息能够被推送到服务器端;
而sessionStorage和localStorage不会被推送到服务器端。
存储大小不同:
cookie最大支持4KB,而sessionStorage和localStorage一般在2.5~10MB
生命周期:
默认情况下,cookie开始于浏览器启动,结束于浏览器关闭,但是可以手动设置cookie的过期时间,同时,到期后被删除;
而对于localStorage,没有过期时间,原则上只要不手动删除,其会一直被保存在本地上;sessionStorage的数据关闭浏览器时清除
被创造的初衷不同:
sessionStorage和localStorage都属于WebStorage,创建他们的目的就是用于存储客户端数据;
而cookie最早在网景的浏览器中被支持,主要目的是为了辨别用户身份而存储在本地终端的数据。
2)前端数据库
前端数据库有WebSql和IndexDB,其中WebSql被规范废弃,他们都有大约50MB的最大容量,可以理解为localStorage的加强版。
3)应用缓存
应用缓存主要是通过manifest文件来注册被缓存的静态资源,已经被废弃,因为他的设计有些不合理的地方,他在缓存静态文件的同时,也会默认缓存html文件。这导致页面的更新只能通过manifest文件中的版本号来决定。所以,应用缓存只适合那种常年不变化的静态网站。如此的不方便,也是被废弃的重要原因。
4)Service Worker
Service Worker本质上也是浏览器缓存资源用的,只不过他不仅仅是cache,也是通过worker的方式来进一步优化。
基于h5的web worker,所以绝对不会阻碍当前js线程的执行,sw最重要的工作原理就是
1、后台线程:独立于当前网页线程;
2、网络代理:在网页发起请求时代理,来缓存文件;
兼容性:
基本上新版浏览器还是兼容滴。之前是只有chrome和firefox支持,现在微软和苹果也相继支持了。
详细资料从这里开始~~~
PWA
PWA全称Progressive Web App,即渐进式WEB应用。
PWA 主要功能:
1) web App Manifest 实现添加至主屏幕,
2) Service Worker 实现离线缓存, (主要功能)
3) push Notification 实现消息推送。
PWA项目实践:
vue cli 3.0中pwa使用了第三方库workbox,Web App 静态资源和请求结果的本地存储的解决方案。
workbox 是由谷歌浏览器团队发布,用来协助创建 PWA 应用的 JavaScript 库。
此时项目中关于PWA的文件如下:
1、package.json中引用了register-service-worker插件
2、根目录下有registerServiceWorker.js
3、public文件夹下有manifest.json,可以根据需要修改其中的内容
module.exports = {
pwa: {
// configure the workbox plugin
workboxPluginMode: 'InjectManifest',
workboxOptions: {
// swSrc is required in InjectManifest mode.
swSrc: 'src/pwa/service-worker.js'
}
}
}
1、 web App Manifest 实现添加至主屏幕
web App Manifest 作为PWA 的 户口本。
web App Manifest,即通过一个清单文件向浏览器暴露 web 应用的元数据,包括名字、icon的URL等,以备浏览器使用,比如在添加至主屏或推送通知时暴露给操作系统,从而增强web应用与操作系统的集成能力。
W3C web App Manifest
1) scope: 定义了web 应用的浏览作用域,比如作用域外的URL 就会打开浏览器而不会在当前PWA里继续浏览。
2) start_url: 定义了一个 PWA的入口页面。
3) orientation: 锁定屏幕旋转。
4) theme_color/background_color:主题色与背景色,用于配置一些可定制的操作系统UI 以提高用户体验。
比如:Android的状态栏,任务栏等。
2、Service Worker 实现离线缓存
LocalServer
1) 让 web应用离线使用的第一次尝试。
2) 2007年,为了让自家的 Gmail、youtube、Google Reader等web应用可以在本地存储数据与离线执行,Google开发了一个浏览器拓展来增强web应用—— Google Gears
3) 在Gears API中,通过向localServer 模块提交一个缓存文件清单来实现离线支持。
Application Cache
1) 让web 应用离线使用的第二次尝试
2) 在localServer的基础上进一步发展
3) 缺点:不可编程、无法清理缓存、几乎没有路由机制等
Service Worker
1) 让web 应用离线使用的第三次尝试
2) 可编程的 Web Worker
3) 像一个位于浏览器与网络之间的客户端代理,可以拦截、处理、响应流的HTTP 请求 (注:浏览器的nginx)
4) 配合Cache Storage APi,可以自由管理 HTTP 请求文件粒度的缓存
Service Worker 缓存策略
Service Worker 出于安全性和其实现原理,在使用的时候有一定的前提条件。
1、要求 HTTPS 的环境或localhost
2、Service Worker 的缓存机制是依赖 Cache API 实现的
3、依赖 HTML5 fetch API
4、依赖 Promise 实现
重要说明:
Service Worker 是支撑PWA作为 下一代 web 应用模型 的最核心技术。Service Worker将在未来十年里成为 web 客户端技术工程化的兵家必争之地。
三、push Notification 实现消息推送
1) push API 的出现则让推送服务具备了向 web应用推送消息的能力。
2) push API 不依赖 web 应用与浏览器UI存活,所以即使是在web 应用与浏览器未被用户打开的时候,也可以通过后台进程接受推送消息并调用 Notification API 向用户发出通知。
觉得本文对你有帮助?请分享给更多人
关注「前端学苑」加星标,提升前端技能