【问题标题】:How to refresh Rails / Sprockets to be aware of new manifest on production server after assets:precompile如何在资产后刷新 Rails / Sprockets 以了解生产服务器上的新清单:预编译
【发布时间】:2015-01-02 08:32:12
【问题描述】:

我们有一个用例,我们需要在部署/重启过程之外运行 assets:precompile,因此最好不必重启 Rails 服务器进程。这在乘客环境中是否可行?

我一直在努力尝试 Rake 任务中的一堆东西并摆弄 Rails.application.config.assets 的东西,但是除了使用 /usr/bin/env touch ~/project/current/tmp/restart.txt 重新启动Passenger 之外,没有什么能让应用程序获取对摘要的更改

【问题讨论】:

  • 如果您使用乘客,您可以touch /tmp/restart.txt吗?
  • 我应该澄清一下,当我说“重新启动服务器”时,我正试图避免这种情况。为了清楚起见,我将编辑帖子。我希望能够将新资产摘要填充到每个正在运行的实例中,但我想不出一种可靠的方法。
  • hmm... 只是胡思乱想,但我想知道您是否可以更新 manifest.yml 文件,然后告诉 sprockets 刷新它。清单将告诉stylesheet_link_tag 'main' 所在的位置。
  • 任何想法如何告诉链轮刷新它?我尝试构建一个 rake 任务,该任务将遍历新创建的 manifest.yml 文件并将其插入到每个根据 Rails.application.config.assets.digests[file] 记录中,但这并没有做任何事情,这使得有意义,因为 rake 任务中的“sprockets”实例与在每个 puppet'ized 实例中运行的实例不同。我曾想过尝试在 redis 中添加某种标志,但后来陷入了“我如何确定每个服务器上的每个实例都正确捕获更新”的问题
  • 我知道了。这是一个艰难的。我遇到了this article也许你可以一起破解livereload,和/或守卫看目录。我希望我能给你一个可靠的答案,但似乎是一个棘手的问题。

标签: ruby-on-rails-3 rake passenger sprockets capistrano3


【解决方案1】:

对于 Rails 4(Sprockets 2.11),您可以:

  Rails.application.assets_manifest = Sprockets::Manifest.new(Rails.env, Rails.application.assets_manifest.path)
  # see sprockets-rails/lib/railtie.rb
  ActionView::Base.assets_manifest = Rails.application.assets_manifest

【讨论】:

  • 这是线程安全的吗?这似乎令人怀疑。例如,如果这是在后台作业中设置的会发生什么?
【解决方案2】:

在生产中更新资产的另一种方式如下:

Rails.application.assets_manifest.instance_eval do
    new_manifest = Sprockets::Manifest.new(manifest.dir, manifest.filename)
    @data = new_manifest.instance_variable_get(:@data)
end

【讨论】:

    【解决方案3】:

    我们最终采用了两部分解决方案:

    第 1 部分是设置应用程序以点击 redis 以存储“资产:版本”(我们只是使用时间戳)。然后,每当我们的流程完成预编译时,我们都会使用最新的时间戳更新此资产版本。

    第 2 部分是我们在主 application_controller 中添加了一个 before_filter :check_assets_version,我们的所有其他控制器都从该控制器继承。这个方法看起来像这样:

      def check_assets_version
        @@version ||= 1
        latest_version = get_assets_version # wrapped call to redis to get latest version
        # clear assets cache if current version isn't the same as the latest version from redis
        unless latest_version.blank? || latest_version.to_s == @@version
          @@version = latest_version
          if Rails.env.production? || Rails.env.sandbox? || Rails.env.experimental?
            nondev_reset_sprockets
          else
            dev_reset_sprockets @@version
          end
        end
      end
    

    这两种重置方法如下所示:

      def nondev_reset_sprockets
        manifest = YAML.load(File.read(Rails.root.join("public","assets","manifest.yml")))
        manifest.each do |key, value|
          Rails.application.config.assets.digests[key] = value
        end
      end
    

    nondev reset 将新生成的清单文件中的每个值“填充”到内存中

      def dev_reset_sprockets(version)
        environment = Rails.application.assets
        environment = environment.instance_variable_get('@environment') if environment.is_a?(Sprockets::Index)
        environment.version = version
      end
    

    开发重置只是踢 sprockets “版本”值,以便它认为(正确地)它需要重新解析并实时重新编译最新的资产。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-14
      • 2013-05-08
      • 1970-01-01
      相关资源
      最近更新 更多