当我在生产模式下部署 rails 应用程序时,它会将日期时间字符串作为查询参数附加到所有静态资产 url 的末尾。这是为了防止浏览器在我重新部署应用程序后使用过时的资产缓存副本。
有没有办法让 Rails 使用自上次部署以来未更改的资产(并且只有未更改的资产)的旧时间戳。我想这样做是为了防止用户不得不重新下载那些没有改变的资产。
当我在生产模式下部署 rails 应用程序时,它会将日期时间字符串作为查询参数附加到所有静态资产 url 的末尾。这是为了防止浏览器在我重新部署应用程序后使用过时的资产缓存副本。
有没有办法让 Rails 使用自上次部署以来未更改的资产(并且只有未更改的资产)的旧时间戳。我想这样做是为了防止用户不得不重新下载那些没有改变的资产。
Capistrano 默认情况下会触及它认为是“资产”的每个文件。正如您所说,这意味着在每次部署之后,rails 都认为每个资产都已更改,并且浏览器每次都会下载更新的版本。
您可以使用以下设置在 Capistrano 中禁用此功能
set :normalize_asset_timestamps, false
如果您使用的是 SVN,那么文件的修改日期应该反映它们在您的存储库中最后修改的日期,所以这应该是完美的。
如果您使用的是 Apache,您可以添加类似的内容来真正让缓存为您工作。这有助于告诉浏览器依赖“缓存控制”指令,这意味着如果它知道资产被缓存,它甚至不会打扰请求它。
#Etags should be based on the file parameters only (default includes INode)
FileETag MTime Size
#Rewrite stuff
RewriteEngine On
#This sets the environment variable (is_versioned) when the URL query string
#looks like ?874353948543 or any string of digits
RewriteCond %{QUERY_STRING} ^[0-9]+$
RewriteRule ^(.*)$ $1 [env=is_versioned:true]
<Directory /deployed-rails-app/public/ >
Options -Indexes FollowSymLinks -MultiViews
AllowOverride None
Order allow,deny
allow from all
#For files, force the browser to rely on cache-control directives and
#Rails asset timestamps by removing Etags and Last-Modified dates
#For all assets that aren't stamped by rails, cache them for ~ 3 hours
Header set "Cache-Control" "max-age=10000"
Header unset Etag
Header unset "Last-Modified"
#For all assets that ARE stamped by rails, cache them for 30 days
Header set "Cache-Control" "max-age=2592000" env=is_versioned
</Directory>
我已经以这种方式设置了我的生产服务器,现在返回的访问者只执行一个请求 (Get /),它返回动态内容并且所有资产 (~ 40 - 50) 都被缓存。
我认为您可以使用 ENV['RAILS_ASSET_ID'] 来更改缓存清除资产 ID。不幸的是,这适用于所有资产。
但如果未设置,则使用资产的源修改时间。如果该文件自您上次使用以来没有被修改过,那应该不是问题。
如果资产 ID 在未更改的情况下发生更改,则可能是因为您的部署过程改变了修改时间,也许您可以考虑对其进行调整。
最后,您始终可以使用自己的自定义方法覆盖 rails_asset_id。
希望这可以帮助。
@Aupajo 我喜欢这个,但我想我可以更进一步。这里的问题是 capistrano 确实会在每次部署时创建所有文件的新副本,因此所有缓存清除字符串都会更改。但是,文件的 MD5 只会在文件内容更改时更改。
当然,生成一个MD5既昂贵又慢,但是你可以把一个文件的MD5缓存在memcache中,(keyed on the change time,好像时间变了MD5可能变了,但是如果时间戳没有变MD5不会改变