nginx 发布前端资源的缓存方案

前言

对于前端开发者来说,最头疼的事情莫过于。当你兴冲冲的给项目打包以后,上传到 nginx 等静态资源服务器发布以后,自己本地验证没问题,以为万事大吉,结果测试人员、用户反馈系统没更新,让你顿时感觉如同吃了苍蝇般难受。

没办法,作为一个专业的开发人员,用户反馈程序出问题,第一时间就要找到问题出现的原因。

于是你开始进行检查确认工作,先是打开浏览器访问系统发现没问题,确实是更新以后的版本。然后你开始对自己更新的过程产生了怀疑,上服务器,检查一下更新以后的资源文件,再三的详细比对,发现确实没问题后,你忽然恍然大悟,原来代码确实没问题,有问题的是浏览器缓存。

解决问题思路

前端打包后的文件,其实就是一些静态资源,我们一般情况下,是直接放在静态资源服务器提供服务的。

一般,解决发布资源缓存这个问题,有几种思路:

1. 浏览器设置每次都重新下载页面的所有的资源。

这个方案有个优点,每次拿到的资源都是重新拉去的最新的资源,所以不存在会缓存的问题。

但是这个方案的缺点非常明显,它直接让缓存失去了自身的意义。没有缓存,增加了服务器的负担,对服务器不太友好,同时也让用户使用网页的体验降低了。

而且,默认情况下,没有浏览器会这么设置。如果需要用这个方式,就需要引导用户这么设置,同时也对用户要求太高。

所以这个方案,不用考虑,直接就可以 pass 掉了。

2. 在静态资源服务器上配置,强制不让浏览器进行缓存。

常见的静态资源服务器,像 nginx、apache 等,确实可以配置让客户端永远不缓存静态资源。

虽然与第一个方案相比,它存在一些优点,比如不需要引导用户对浏览器进行配置。

但是弊病和第一种思路一样,对用户和服务器都极其不友好,所以这个方案也可以被 pass 掉了。

3. 最好的解决方案

其实有一种比较好的解决方案,需要前端和静态资源服务器配合起来达到。

前端资源其实分为几类:

  1. 内容会变化,但是文件名不会变,用户也只能通过某个路径访问到,最典型的就是页面入口的 index.html 文件
  2. 内容会变化,文件名也可以变化,比如每次打包生成的 js文件、css 文件、图片资源等
  3. 内容不会变化,文件名也不会变化,比如直接在 html 中引入的第三方包

针对这几种不同的解决方案,可以针对性的作优化。

第一类,可以采用 Etag 的缓存策略。

如果没了解过这个名词的童鞋,可以 mdn 上了解下相关知识:ETag - HTTP | MDN。

简而言之,如果采取了 Etag 策略,那么每次请求某个资源的时候,服务器会在响的的请求头里返回 Etag 标签:

下次,如果再请求同样的资源的时候,浏览器就会在请求头里带上这个 Etag,让服务器进行对比,如果 Etag 能够匹配上,就返回 304,浏览器就明白,不用重新下载资源,直接用本地缓存就行;否则浏览器会返回200,并返回完整的请求资源。

比如,想要在 nginx 中配置 etag,可以参考下面的链接:

Module ngx_http_core_module

直接这样配置即可,同时要在 header 中加上 cache control 控制,让浏览器对 html 文件应用 no-cache 规则。

location ~ .*\.(?:htm|html)$ {...add_header Cache-Control "no-cache";etag on;...
}

不了解 cache-control 的童鞋,可以参考下 mdn 的文档:
Cache-Control - HTTP | MDN

这样配置了以后,对于所有的 html 文件,就达到了当文件没更新的时候,返回 304,当文件更新了,自动拉取最新的资源的目的。

第二类,直接采用强制浏览器缓存的方法。

对于第二类资源,我们可以通过添加 hash 的方式保证,即使前端版本更新了,文件名也不一样,那么我们就不需要像第一种方式一样,通过 Etag 方式去缓存了。

因为即使是 Etag 策略,其实也是会消耗请求资源的。对于这种发布了就不会更改的内容,直接可以通知浏览器长期缓存即可。

想达到这种效果,直接通过配置 cache control header 即可。

location ~ .*\.(?:js|css|jpg|jpeg|gif|png)$ {...add_header Cache-Control "public, max-age=31536000";add_header Last-Modified "";etag off;...
}

直接配置对于第二类资源,关闭 Etag,同时设置强制缓存,同时设置上一年的缓存期。

这样设置了以后,当浏览器再次请求该资源时候,会查看浏览器之前缓存的该资源是否还在有效期以内,如果在,便会直接应用该资源,不会向浏览器再次发起请求了;否则,会重新发起请求,请求该资源。

第三类资源的解决方案,其实跟第二类一样,通过添加 hash 值或者 timeStamp,用以区分资源,达到每次更新版本后,请求的资源不一致。

对于这两类资源的处理,在 nginx 上的配置,也并无差别,可以等同对待。

对于前端来说,就比较麻烦一些。

下面列举一些,在常用的前端框架的脚手架中,该如何配置,以达到自动添加 timeStamp 的效果吧。

  • create-react-app

在 react 这个官方脚手架中,支持从环境变量传值: Adding Custom Environment Variables | Create React App

所以,我们直接在模板中,替换调传入的值即可。

/** .env 文件 */
REACT_APP_WEBSITE_NAME=测试标题
REACT_APP_TIMESTAMP=1639814656911
/** html 模板文件,通过传值,替换掉模板中的内容 */
<title>%REACT_APP_WEBSITE_NAME%</title>
<script src="%PUBLIC_URL%/config.js?timeStamp=%REACT_APP_TIMESTAMP%"></script>
  • vue-cli

在 vue 脚手架中,可以通过重载 webpack 配置,来设置变量。

/*** @type {import('@vue/cli-service').ProjectOptions}*/
module.exports = {chainWebpack: (config) => {config.plugin('html').tap((args) => {args[0].timeStamp = Date.now();return args;});},
};

然后通过在 index.html 模板中,采用 lodash template 的方式,应用变量。

<script src="<%= BASE_URL %>config.js?timeStamp=<%= htmlWebpackPlugin.options.timeStamp %>"></script>

详细用法可以参考官方文档:HTML and Static Assets | Vue CLI

后记

其实对于同一个问题,往往会有多种不同的解决方案。有时候多研究一下,多思考一下,综合考量,就可以找出一种比较好的解决方案。

nginx 发布前端资源的缓存方案相关推荐

  1. Nginx做前端代理时缓存与否的性能差别

    Nginx做前端代理,后端两台apache upstream webservers {------------------定义在http段server 172.16.20.31 ;server 172 ...

  2. ngnix mysql 缓存清除_利用Proxy Cache使Nginx对静态资源进行缓存

    前言 Nginx是高性能的HTTP服务器,通过Proxy Cache可以使其对静态资源进行缓存.其原理就是把静态资源按照一定的规则存在本地硬盘,并且会在内存中缓存常用的资源,从而加快静态资源的响应. ...

  3. nginx配置静态资源,重新发布后,浏览器缓存导致异常原因和解决

    原因: nginx作为静态资源服务器,重新构建后发生浏览器页面直接取缓存中的js等文件名,但是由于服务器中文件已经被替换导致出现异常. 浏览器在下次请求这个资源的时候不会将请求发向后端,而是直接从缓存 ...

  4. win10 nginx部署前端项目(静态资源服务器和HTML)

    win10 nginx部署前端项目(静态资源服务器和HTML) niginx的安装和启停操作参照博客:https://blog.csdn.net/qq_26666947/article/details ...

  5. 基于微前端qiankun的多页签缓存方案实践

    作者:vivo 互联网前端团队- Tang Xiao 本文梳理了基于阿里开源微前端框架qiankun,实现多页签及子应用缓存的方案,同时还类比了多个不同方案之间的区别及优劣势,为使用微前端进行多页签开 ...

  6. 使用 Nginx 管理你的前端资源

    前言 在前端项目开发中,我们可以启动 devserver 管理静态资源服务,但是发布线上后要保证稳定,一般会选择一个高效能 + 稳定的静态服务器来管理前端资源. 作为前端工程化的关键一环节,这一篇我们 ...

  7. 前端网页发布到nginx_通过nginx部署前端代码实现前后端分离

    实现前后端分离,可以让前后端独立开发.独立部署.独立单测,双方通过JSON进行数据交互. 对于前端开发人员来说,不用每次调试都需要启动或配置Java/Tomcat运行环境:对于后端开发人员来说 ,也不 ...

  8. nginx 部署前端项目,不缓存html文件,项目发版后,不用手动刷新页面

    nginx 部署前端项目,不缓存html文件,项目发版后,不用手动刷新页面 location / {expires 1h;root /home/test/vue/dist/;index index.h ...

  9. 前端访问nginx发布的视频文件,实现在线播放

    文章目录 简介 依赖插件 nginx 配置 前端配置 css文件配置 html页面脚本 js脚本 实现效果 简介 主要是为了解决观看本地的视频文件,有时也需要在服务器上发布预览视频文件,所以就做了这么 ...

最新文章

  1. 未处理的异常导致基于 ASP.NET 的应用程序意外退出
  2. SpringMVC如何实现aop
  3. Python学习笔记(八)—使用正则获取网页中所需要的信息。
  4. python【数据结构与算法】判断对称二叉树
  5. 1319. 连通网络的操作次数
  6. 行内块元素(HTML、CSS)
  7. (Spring Cloud微服务实战-书中之坑)spring cloud zuul统一处理业务异常,并且需要响应状态为200...
  8. 今天起改用mac的marsedit写博
  9. 【C语言】10-字符和字符串常用处理函数
  10. win10删除自定义的背景图片历史记录
  11. Linux上的arping命令介绍
  12. javascript获取浏览器窗口大小 获取屏幕,浏览器,网页高度宽度
  13. Flash游戏开发技术分析(上)
  14. 第149篇 笔记-web3
  15. ChatGPT宝藏插件丨装上之后,上网、语音聊天、一键分享对话……简直让你爽到起飞!
  16. 梯度下降算法和牛顿算法原理以及使用python用梯度下降和最小二乘算法求回归系数
  17. 快速理解数据库函数依赖(平凡函数依赖、非平凡函数依赖、完全函数依赖、部分函数依赖、传递依赖)
  18. python_爬虫 16 Scrapy框架之(二)快速入门
  19. IntelliJ IDEA汉化,IntelliJ IDEA安装中文语言包。IntelliJ IDEA 2020.1正式发布,支持中文啦。
  20. 爬虫期末考试笔记(填空题)

热门文章

  1. 50ETF期权新手的一些投资技巧
  2. 玫琳凯生产并捐赠洗手液以抗击COVID-19大流行
  3. TI 高精度实验室《运算放大器系列--带宽》
  4. 恢复以外丢失的Wrod文档
  5. vue data 中的 return 用法
  6. linux mrtg 进程名称,linux mrtg
  7. Array.from()与Array.of()
  8. easyExcel导出数据及单元格多张图片
  9. 学习随笔#8 深度优先算法和广度优先算法
  10. 什么是RGB值,RGBA以及十六进制的RGB