Статическое кэширование ресурсов в Heroku с помощью Jammit путем изменения ActionController::Base#page_cache_directory
-
12-11-2019 - |
Вопрос
Я пытаюсь использовать Jammit для упаковки CSS и JS для приложения Rails, развернутого на Heroku, которое не работает из коробки из-за файловой системы Heroku, доступной только для чтения.В каждом примере, который я видел о том, как это сделать, рекомендуется создавать все упакованные файлы ресурсов заранее.Из-за развертывания Heroku на основе Git это означает, что вам нужно делать отдельную фиксацию в вашем репозитории каждый раз, когда эти файлы изменяются, что для меня не является приемлемым решением.Вместо этого я хочу изменить путь, который Jammit использует для записи кэшированных пакетов в #{Rails.root}/tmp/assets
(путем изменения ActionController::Base#page_cache_directory
), который доступен для записи на Heroku.
Чего я не понимаю, так это того, как будут использоваться кэшированные файлы, не попадая каждый раз в стек Rails, даже используя путь по умолчанию для кэшированных пакетов.Позвольте мне объяснить, что я имею в виду:
Когда вы включаете пакет с помощью помощника Jammit, это выглядит примерно так:
<%= include_javascripts :application %>
который генерирует этот тег скрипта:
<script src="/assets/application.js" type="text/javascript"></script>
Когда браузер запрашивает этот URL-адрес, на самом деле происходит то, что он перенаправляется на Jammit::Controller#package
, который отображает содержимое пакета в браузере , а затем записывает кэшированную копию в #{page_cache_directory}/assets/application.js
.Идея заключается в том, что этот кэшированный файл создается по первому запросу, и последующие запросы должны обслуживать кэшированный файл напрямую, не попадая в стек Rails.Я просмотрел код Jammit и не понимаю, как это должно произойти.Что препятствует последующим запросам к /assets/application.js
от простой маршрутизации к Jammit::Controller
снова и никогда не используя кэшированный файл?
Я предполагаю, что где-то есть промежуточное программное обеспечение Rack, которого я не вижу, которое обслуживает файл, если он существует, и пересылает запрос контроллеру, если его нет.Если это так, то где этот код?И как это будет работать при смене ActionController::Base#page_cache_directory
(эффективно изменяя место, куда Jammit записывает кэшированные пакеты)?С #{Rails.root}/tmp
находится над корнем общедоступного документа, нет URL-адреса, который соответствовал бы этому пути.
Решение
Отличный вопрос!Я сам этого не настраивал, но это то, на что я давно хотел обратить внимание, так что вы побудили меня сделать это.Вот что я бы попробовал (скоро я сам попробую, но вы, вероятно, меня опередите).
config.action_controller.page_cache_directory = "#{Rails.root}/tmp/page_cache"
Теперь измените свой config.ru на:
require ::File.expand_path('../config/environment', __FILE__)
run Rack::URLMap.new(
"/" => Your::App.new,
"/assets" => Rack::Directory.new("tmp/page_cache/assets"))
Просто убедитесь, что в нем ничего нет. public/assets
, поскольку это никогда не будет поднято.
Записи:
- Это для Rails 3.Не уверен в решении под Rails 2.
- Это выглядит как
Rack::Directory
устанавливает значение заголовков управления кэшированием на 12 часов, чтобы Heroku кэшировал ваши ресурсы для удаления лака.Не уверен, устанавливает ли Jammit это в своем контроллере, но даже если это не так, оно будет кэшировано довольно быстро. - Героку также устанавливает
ENV['TMPDIR']
теперь тоже, так что вы можете использовать это вместоRails.root + '/tmp'
если вы пожелаете.
Другие советы
Это может быть полезно, это для другого драгоценного камня, но идея схожа, и я пытаюсь заставить ее работать с простыми помощниками по активам.
http://devcenter.heroku.com/articles/using-compass
К сожалению, кажется довольно сложным заставить rails сделать это без исправления / перезаписи модуля asset helpers (который напоминает связанные спагетти).