美文网首页小叶同学实践手册
前端SPA应用缓存问题解决与实践

前端SPA应用缓存问题解决与实践

作者: 叶叶叶同学 | 来源:发表于2021-04-08 18:03 被阅读0次

前言

前端SPA应用缓存问题
原先的客户端已经加载过资源了(进过一次页面),然后更新静态资源,客户端重新进入页面,还是访问的之前未更新的资源,需要客户端手动刷新才能获取最新的资源(或者过段时间本机缓存失效后,重新进)

要解决问题,有先决的理论知识先要了解

浏览器缓存类型

分两种:

  • 强缓存
  • 协商缓存

强缓存

这种机制下,浏览器会先找本地缓存,命中则不会从服务器请求,并返回200状态码,且附有disk cache或者memory cache字样

image.png

Memory cache: 很好理解,内存中的缓存,较小,快,拥有内存存储的特点,不赘述

Disk cache: 也很好理解,磁盘中的缓存,较大,比内存慢,拥有磁盘存储的特点,不赘述

协商缓存

这种机制,强缓存失效后,浏览器会携带缓存标识向服务器发起请求,服务器根据标识决定是否使用缓存

  • 协商缓存生效,返回304和Not Modified
  • 协商缓存失效,返回200和请求结果

首先一点,就是“浏览器会携带缓存标识”,这个标识是什么,有两种

  • Last-Modified
  • ETag

Last-Modified 和 If-Modified-Since

很好理解,上一次修改的时间。
浏览器在第一次访问资源时,服务器返回资源的同时,在 response header 中添加 Last-Modified 的 header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header
浏览器下一次请求这个资源,浏览器检测到有 Last-Modified 这个 header,于是添加 If-Modified-Since 这个 header,值就是 Last-Modified 中的值。服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回 304 和空的响应体,浏览器直接从缓存读取
如果 If-Modified-Since 的时间小于服务器中这个资源的最后修改时间,说明文件有更新,则返回新的资源文件和 200

ETag 和 If-None-Match

Etag 是服务器响应请求时返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag 就会重新生成
浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的 Etag 值放到 request header 里的 If-None-Match 里,服务器只需要比较客户端传来的 If-None-Match 跟自己服务器上该资源的 ETag 是否一致,就能很好地判断资源相对客户端而言是否被修改过了
如果服务器发现 ETag 匹配不上,那么直接以常规 GET 200 回包形式将新的资源(当然也包括了新的 ETag)发给客户端
如果 ETag 是一致的,则返回 304 指示客户端直接使用本地缓存即可

好,原理讲了,现在凡是用到nginx的,基本上自动都会实现了ETag和Last-Modified,也就是说,这部分实现机制,已经是默认的!不需要你另加处理。

好,问题来了,如何处理前端SPA应用的缓存问题呢?

前端SPA应用缓存策略

现在的SPA要么Vue要么React要么Angular

默认情况下,我们会看到:


image.png

即所有资源第一次进,强缓存,第二次进,无意外情况下,会执行协商缓存。

之所以会出现SPA缓存问题,在于index.html是304,那么客户端读取到的,有可能是本地的Not Modified,那么继续下去,读的依旧是本地的disk cache

如何解决问题呢?

这里有个特性,SPA通过webpack打包,一般默认会带有contenthash值,即当对应文件有改动,这个contenthash值才会改变,进而改变打包出来的文件名,意味着只有改变了的文件,文件名才会变,没有改变的文件是不会变的

  • 对首页index.html 取消强缓存。在nginx配置上 no cache
location / {
        root   /home/app_front/online_clinc;
        ...
        add_header Cache-Control "no-cache, no-store";
    }
  • 对除首页外的文件,设置强缓存且过期时间设置大点,比如180d
location ~* \.(gif|jpg|jpeg|png|css|js|ico|eot|otf|fon|font|ttf|ttc|woff|woff2)$ {
        root /home/app_front/online_clinc;
        expires 180d;
        add_header Cache-Control "public";
    }

如果需要对特殊的文件特殊处理,比如文字类型的文件设置更大的缓存时间或者别的,可以参考上述语法单独加映射

修改后,service nginx reload一下,浏览器可以看到差别:

image.png
image.png

index.html一直是200,且从服务器直接读取,而所有其他的静态文件,均从memory or disk cache读取

好,那么接下来如果有更新,可以想象,变化的文件有

  • index.html - 因为引入的入口js一定会变名字
  • 对应的入口js文件以及涉及到改动的js

而由于index.html一直是请求服务器的,那么得到的入口js也必然是最新的,意味着如果没改动的,走本地强缓存,有改动的,会请求最新的,之后请求会走本地强缓存。

大部分都走了本地强缓存,少部分有更改的,会请求最新,之后请求会走本地强缓存

Problem solved.

总结

解决前端SPA缓存问题:

  • 对首页index.html 取消强缓存。在nginx配置上 no cache
  • 对除首页外的文件,设置强缓存且过期时间设置大点,比如180d

相关文章

  • 前端SPA应用缓存问题解决与实践

    前言 前端SPA应用缓存问题原先的客户端已经加载过资源了(进过一次页面),然后更新静态资源,客户端重新进入页面,还...

  • vue路由的两种模式

    hash与history 对于Vue 这类渐进式前端开发框架,为了构建SPA(单页面应用),需要引入前端路由系...

  • SPA及其优缺点

    SPA:单页面web应用,一般整个应用只有一个html页面,通过前端路由实现无刷新跳转。 Vue就是SPA应用的典...

  • SPA及其优缺点

    SPA:单页面web应用,一般整个应用只有一个html页面,通过前端路由实现无刷新跳转。 Vue就是SPA应用的典...

  • 好程序员Web前端培训干货详解Vue-Router路由与配置

    好程序员web前端培训干货详解Vue-Router路由与配置,现在的很多应用都流行SPA应用(singe page...

  • vue-router 原理

    1、前端路由 在 Web 前端单页应用 SPA(Single Page Application)中,路由描述的是 ...

  • cordova实践建议

    最佳开发实践 SPA设计 建议使用SPA(Single Page Application,单页应用)设计来开发你的...

  • 第三天_路由_Vue.js2.0+Node+ES6+MongoD

    什么是前端路由? 什么时候使用 优点与缺点 vue-router用来构建SPA 单页Web应用(single pa...

  • FY-7216 9-vueRouter

    vue-router Router 路由是伴随着 SPA (单页面应用存在的)spa出现后,前端可以自由的控制组件...

  • hash 和history 的原理和区别

    目前单页应用(SPA)越来越成为前端主流,单页应用一大特点就是使用前端路由,由前端来直接控制路由跳转逻辑,而不再由...

网友评论

    本文标题:前端SPA应用缓存问题解决与实践

    本文链接:https://www.haomeiwen.com/subject/szyvkltx.html