VueJS/浏览器缓存生产构建

新手上路,请多包涵

我有一个 VueJS 应用程序。每当我运行 npm run build 它会创建一组新的 dist/* 文件,但是,当我将它们加载到服务器上(删除旧版本后)并在浏览器中打开页面时,它加载旧版本(我假设来自缓存)。当我刷新页面时,它加载新代码没问题。

这是我的 index.html:

 <!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
        <meta http-equiv="cache-control" content="max-age=0" />
        <meta http-equiv="cache-control" content="no-cache" />
        <meta http-equiv="expires" content="-1" />
        <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
        <meta http-equiv="pragma" content="no-cache" />
        <link rel="stylesheet" href="/static/css/bootstrap.min.css"/>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>

有没有办法强制它每次都加载新代码或(理想情况下)检查旧文件是否从服务器中消失,然后刷新浏览器?

原文由 ierdna 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 478
2 个回答

毫无疑问,这个问题很烦人。必须使用在标头中发送的自定义前端版本端点来解决它。我使用 rails 后端和 Vue + Axios 作为前端。请注意,我不需要服务人员,因此不使用服务人员。

本质上,只要有获取请求并且应用程序的版本已更改(服务器可以通知相同),我就会重新加载

axiosConfig.js

 axios.interceptors.response.use(
  (resp) => {
    const fe_version = resp.headers['fe-version'] || 'default'
    if(fe_version !== localStorage.getItem('fe-version') && resp.config.method == 'get'){
      localStorage.setItem('fe-version', fe_version)
      window.location.reload() // For new version, simply reload on any get
    }
    return Promise.resolve(resp)
  },
)

Rails 后端

application_controller.rb

 after_action :set_version_header

def set_version_header
  response.set_header('fe-version', Setting.key_values['fe-version'] || 'default')
end

application.rb (CORS 配置假设 Vue 在端口 8080 上运行)

 config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins ['localhost:8080', '127.0.0.1:8080']
    resource '*', expose: ['fe-version'], headers: :any, methods: [:get, :post, :delete, :patch], credentials: true
  end
end if Rails.env.development?

在这里写了一篇详细的文章: https ://blog.francium.tech/vue-js-cache-not-getting-cleared-in-production-on-deploy-656fcc5a85fe

原文由 bragboy 发布,翻译遵循 CC BY-SA 4.0 许可协议

我们在同样的问题上苦苦挣扎,发现有些人的浏览器甚至不会拉到最新版本,除非他们手动刷新。我们在各个层都遇到了缓存问题,包括我们托管文件的 CDN。

我们还努力维护版本并在出现问题时快速重新部署以前的版本。

我们的解决方案(使用基于 vue-cli Webpack 的项目):

1)我们构建发行版以具有特定于版本的文件夹而不是“静态”。这也有助于我们跟踪构建并在需要时“撤消”部署。要更改“静态”目录,请更改 index.js 中“build”下的“assetsSubDirectory”,并将“assetsPublicPath”更改为您的 CDN 路径。

2)我们使用 Webpack Assets Manifest 构建一个 manifest.json 文件指向所有资产。我们的清单包括所有文件的散列,因为它是一个高安全性的应用程序。

  1. 我们将版本化文件夹(包含 js 和 css)上传到我们的 CDN。

  2. (可选)我们在后端服务器上托管一个动态 index.html 文件。样式表和脚本的链接由后端服务器使用从 manifest.json 上的数据中提取的模板系统填充(参见 #5)。这是可选的,因为您可以使用下面评论中的 force-reload 选项,这不是很好的体验,但确实有效。

  3. 要发布新版本,我们将 manifest.json 发布到后端服务器。我们通过 GraphQL 端点执行此操作,但您可以手动将 json 文件放在某处。我们将其存储在数据库中并使用它来填充 index.html 并使用它来使用文件哈希验证文件(以验证我们的 CDN 未被黑客入侵)。

结果:即时更新和轻松跟踪和更改版本的能力。我们发现它会立即在几乎所有用户的浏览器中拉取新版本。

另一个好处:我们正在构建一个需要高安全性的应用程序,并将 index.html 托管在我们(已经安全的)后端使我们能够更轻松地通过我们的安全审计。


编辑 2/17/19

我们发现,尽管没有缓存标头,但公司网络仍在进行代理缓存。 IE 11 似乎也忽略了缓存头。因此,一些用户没有获得最新版本。

我们有一个在构建时递增/定义的 version.json。版本号包含在 manifest.json 中。构建包会自动上传到 S3。然后我们将 manifest.json 传递到后端(我们在管理区域的入口页面上执行此操作)。然后,我们在该 UI 上设置“活动”版本。这使我们能够轻松更改/还原版本。

后端将“currentVersion”作为所有请求的响应标头。如果 currentVersion !== 版本(如 version.json 中定义),那么我们要求用户单击以刷新他们的浏览器(而不是强制他们)。

原文由 For the Name 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题