我在production.rb中使用它:
config.public_file_server.headers = {
'Cache-Control' => 'public, s-maxage=31536000, maxage=31536000',
'Expires' => "#{1.year.from_now.to_formatted_s(:rfc822)}"
}
我通过cdn.mydomain.com使用公共文件,该文件是从www.mydomain.com读取的,它复制了我用public_file_server.headers设置的www.mydomain.com的缓存控件。
问题是我希望/ public中的某些文件不具有那些缓存控制,例如我的service-worker.js
例如,是否可以仅针对/ public中的一个文件夹设置那些缓存控制?
另一种解决方案是删除此public_file_server.headers配置,并在cdn级别上设置缓存控制(我使用cdn.mydomain.com/publicfile),并使www.mydomain.com/serviceworker不受缓存控制,服务人员。
但是也许有机会在Rails级别进行配置?
答案 0 :(得分:4)
我遇到了完全相同的问题:使用CDN(Cloudfront)使用Rails构建的PWA。对于要在不久的将来过期的情况下使用缓存头的资产,但是ServiceWorker需要Cache-control: No-cache
。
由于CloudFront本身不允许添加或更改标题,因此我需要在应用程序级别上解决方案。经过一番研究,我在blogpost中找到了一个解决方案。这个想法是通过public_file_server.headers
设置标题,并添加一个中间件来更改ServiceWorker文件的名称。
这是我使用的代码:
production.rb:
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.public_file_server.headers = {
'Cache-Control' => 'public, s-maxage=31536000, max-age=15552000',
'Expires' => 1.year.from_now.to_formatted_s(:rfc822)
}
if ENV['RAILS_SERVE_STATIC_FILES'].present?
config.middleware.insert_before ActionDispatch::Static, ServiceWorkerManager, ['sw.js']
end
app / middleware / service_worker_manager.rb:
# Taken from https://codeburst.io/service-workers-rails-middleware-841d0194144d
#
class ServiceWorkerManager
# We’ll pass 'service_workers' when we register this middleware.
def initialize(app, service_workers)
@app = app
@service_workers = service_workers
end
def call(env)
# Let the next middleware classes & app do their thing first…
status, headers, response = @app.call(env)
dont_cache = @service_workers.any? { |worker_name| env['REQUEST_PATH'].include?(worker_name) }
# …and modify the response if a service worker was fetched.
if dont_cache
headers['Cache-Control'] = 'no-cache'
headers.except!('Expires')
end
[status, headers, response]
end
end