【问题标题】:How to tell Rails assets that new public asset file was generated如何告诉 Rails 资产新的公共资产文件已生成
【发布时间】:2014-11-19 06:57:41
【问题描述】:

我有一个 Rails 应用程序,它根据您访问网站的域动态创建和编译资产(比如说不同的颜色,颜色值存储在数据库中)

假设www.hello.example 它将生成public/assets/hello-application-52777d36dec6f6e311560156da9da1c2.css,因此浏览器源文件将指向

layout:
= stylesheet_link_tag 'hello-application'

generated html:
<link href="/assets/hello-application-52777d36dec6f6e311560156da9da1c2.css" media="all" rel="stylesheet" />

如果添加www.goodbye.example,它将编译public/assets/goodbye-application-52777d36dec6f6e311560156da9da1c2.css,因此浏览器源文件将指向

layout:
= stylesheet_link_tag 'goodbye-application'

generated html:
<link data-turbolinks-track="true" href="/assets/goodbye-application-52777d36dec6f6e311560156da9da1c2.css" media="all" rel="stylesheet" />

资产即时正确编译,无需重新启动服务器。

如果我重新启动服务器,上面的示例可以正常工作

我想不通的是如何告诉 Rails 生成了新的公共资产文件,以便 = stylesheet_link_tag 'goodbye-application' 将其接收 无需重新启动生产服务器强>。

我的猜测是告诉 Rails 重新加载 public/manifest.json 有什么事情要做,我只是想不通

  • Rails 4.0.2
  • Ruby 2.1
  • 独角兽生产服务器

我的功能有点类似于krautcomputing article,但是他用“Digested”解决了这个问题,它不适用于 rails 4(+ 很快就会被弃用)


更新

一个家伙提供了一个答案(他已经删除)建议我不需要这样做,因为独角兽的重启时间为零,所以我可以重启独角兽,它会加载新的公共资产......这是真的,在我问这个问题之前,我就是这样做的。但是我正在寻找避免这种情况的解决方案。 (假设用户每天生成 1000 种样式)

他还建议使用 Grunt...嗯,这是 B 计划,我真的想知道 Rails-sprockets 中是否有办法做到这一点:)

【问题讨论】:

  • Rails 现在是如何做到这一点的?您现在使用什么配置来完成动态生成?
  • 旁白:您应该尽快从 rails v4.0.2 升级到最新的 v4.0 版本。 v4.0.3 引入了几个安全补丁。
  • 如何根据将要生成的 CSS 名称制作= stylesheet_link_tag 'Variable' 。例如,再见一个将具有 goodbye.css,另一个将具有您选择的名称?
  • 可能有点幼稚,但您知道添加新资产的确切时间,将其发送到 shell(或后台任务)并运行 rake assets:precompile ?这将生成manifest 文件。尽管不完全确定正在运行的 rails 进程是否会启动它。它不像自动重新编译那样干净,但比重新启动独角兽进程更好:)
  • Rails 不会获取清单更改甚至新清单。我也在为此寻找解决方案,以便在开发时更好地模拟我的生产环境。我已经完成了对 sprockets 的完整 gulp 替换,但 rails 不想在请求之间获取新清单。

标签: ruby-on-rails ruby-on-rails-4 sprockets


【解决方案1】:

为什么不直接推出自己的辅助方法?

def subdomain_application_stylesheet_link_tag(subdomain)
  if Rails.env.production?
    # This assumes you've precompiled the spreadsheet into the public directory via sprockets
    stylesheet_link_tag File.basename(
      Dir.glob("#{Rails.root}/public/assets/#{subdomain}-application-*.css").first
    )
  else
    # Logic to development stylesheet selection
  end
end

【讨论】:

    【解决方案2】:

    这是清单重新加载问题的完整解决方案。如原始帖子中所述,除非您完全重新加载服务器(或杀死作品等),否则您动态生成的新 manifest.json 不会重新加载。重申一下:

    如果您要动态创建资产“实时”,以及清单 为了防止缓存,Sprockets 不会重新加载清单 请求。

    我需要这种清单重新加载功能来进行开发,只是因为我正在使用 Gulp 滚动我自己的资产管道以提高性能。基本上,使用这个解决方案可以让资产完全按照它们在生产中的方式运行,同时在使用新清单进行开发时仍然能够实时重新加载它们......非常漂亮,我希望你发现它对你的生产需求有用。

    创建文件 config/initializers/live-manifest.rb:

      require 'sprockets/rails/helper'
      module Sprockets
        module Rails
          module Helper
            def asset_digest_path(path, options = {})
              # create the new manifest, overriding sprockets' old one
              if assets_manifest and manifest = Sprockets::Manifest.new(assets, Dir.glob(File.join(assets_manifest.dir, 'manifest-*.json')).first)
                if digest_path = manifest.assets[path]
                  return digest_path
                end
              end
    
              if environment = assets_environment
                if asset = environment[path]
                  return asset.digest_path
                end
              end
            end
          end
        end
      end
    

    此外,如果您愿意,我们非常欢迎您自定义新的清单目录。从 Dir.glob 方法调用中可以看出,我的位置与上一个位置相同,但名称不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多