11

我有一个脚本 3rd 方网站正在使用:/assets/script.js. 出于显而易见的原因,我不能在每次部署时都要求他们更改链接以指向脚本的最新指纹版本。我遇到了一些缓存问题,用户仍然可以看到旧版本的/script.js. 有没有办法让缓存直接消失script.js而不是 script-9dc5afea3571ba2a883a72b0da0bb623.js

更多信息:Passenger + Nginx 上的 Rails。寻找提供script.js文件的方法,而不是指纹文件并在每次部署时使缓存无效。

我考虑过根据部署 git 修订添加 ETag,但不知道如何执行此操作。Nginx 没有内置的 ETags 支持。有不受支持的旧第三方模块可以执行此操作。我可以使用add_header Etag="something"它,但是如何在那里添加 git 版本。

还有其他想法和选择吗?

谢谢!

4

8 回答 8

9

如果您有一个名称是公共接口一部分的脚本,那么您需要明确地开始对该脚本进行版本控制,并为旧客户端保留旧版本。

例如 /assets/script.1.0.js、/assets/script.1.1.js 等

关键部分是您需要保留旧的,并且代码不会在没有明确更改名称的情况下更改。Rails 资产管道无法为您执行此操作,因为通常只有最新版本的脚本保持最新。

与所有公共接口一样,与仅用于内部的脚本相比,您将需要花费更多时间来管理此过程。

于 2012-12-26T03:44:07.990 回答
3

我建议使用 ETag。将 ETag 标头添加到您的响应 http://en.wikipedia.org/wiki/HTTP_ETag

对于脚本的每个版本,将 ETag 标头设置为不同的唯一字符串。这将确保浏览器在您部署新版本时获得新版本的脚本。

于 2012-12-27T20:59:11.573 回答
3

nginx is able to generate etags in the latest version: http://nginx.org/en/docs/http/ngx_http_core_module.html#etag

I've also seen the configuration below here: https://serverfault.com/questions/426260/nginx-cache-control

location /static {
  alias /opt/static/blog/;
  access_log off;
  etags on;
  etag_hash on;
  etag_hash_method md5;
  expires     1d;
  add_header Pragma "public";
  add_header Cache-Control  "public, must-revalidate, proxy-revalidate";
}
于 2013-03-14T12:51:29.897 回答
1

如果您使用 Capistrano,您可以编写一个任务,在您的资产预编译后将脚本从 Public/assets 复制到 Public 中的另一个目录(即 Public/scripts)。

于 2013-03-15T18:42:08.557 回答
1

我用于更新资产的是:

  1. 增加喜欢config.assets.version_config/application.rb

    #Version of your assets, change this if you want to expire all your assets
    config.assets.version = '1.1'
    
  2. bundle exec rake assets:precompile RAILS_ENV=production RAILS_GROUPS=assets

  3. 应用重启,清空网络服务器缓存(如果有)

于 2013-03-12T04:17:51.450 回答
1

遵循 ETag 的建议,您可能会发现这个 gem 很有用:bust_rails_etags。它允许您在每次部署时设置用于生成 ETag 的密钥,这样,每次部署您的应用程序时,您的 ETag 都会更改(因此缓存的脚本将失效)。作者使用 Heroku 版本号的示例作为每次部署时更改的密钥。

于 2012-12-28T14:00:54.730 回答
1

您想要第三方网站的非指纹资产 URL。 例如:assets/public_api.js

有一些插件或 gem 将指定的资产排除在指纹之外。然而,rails 以一种也创建非指纹文件的方式改变了预编译过程。因此这不是问题。更多信息在这里。

当资产没有指纹时,如何确保您的客户正在加载最新部署的脚本?

我建议youTube 用来公开他们的API的解决方案。基本上你所有的 assets/public_api.js 都是这样做的,它将另一个脚本标签注入到 dom 中。注入的那个会加载实际的 API 代码。现在你的 assets/public_api.js 变成 assets/public_api.js.erb 并且看起来像这样:

var tag = document.createElement('script');
tag.src = "<%=asset_path('/assets/javascripts/acctual_api')%>";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

请注意如何将 tag.src设置为/assets/javascripts/acctual_api的当前指纹路径。这样,您的用户将始终获得最新编译的 acctual_api 脚本。

如何更新 assets/public_api.js 的 ETAG?

我想您使用 Capistrano 或类似的基于配方的部署解决方案。也许您可以添加一个部署步骤,在重新启动之前更新服务器配置文件。它应该只是更新:

add_header Etag="update_me_on_deploy"

请注意,即使采用这种方法,您仍应使用版本化的 (assets/public_api.0.js) 公共脚本。

于 2013-03-15T14:56:05.233 回答
1

那么您可以删除文件的指纹:

asset_path('script.js', :digest => false)

希望能帮助到你

或者,您可以根据需要使用此 gem:https ://github.com/sophlenz/digestion

但是:Rails 资产管道现在可以编译带有和不带有摘要的资产文件。

因此,在您生成资产后,通常您会将 script.js?xxxxx 和 script.js 放入您的 public/assets 文件夹。

于 2013-03-15T19:00:26.770 回答