2

我们经常需要从我们的 Javascript 中引用 Rails 应用程序资产。我已经看到了创建 assets.js.erb 文件并在其中包含对资产的引用的方法。与此处的示例类似:通过构建所有资产路径值来避免 *.js.erb 文件

我认为这很混乱,我想加入清单生成并同时生成 manifest.js。我想出了以下方法来做到这一点https://gist.github.com/49d3f12bed298f0685a1

当您运行 assets:precompile 时,这可以正常工作,但是,对于开发,我需要动态生成这个 manifest.js。我找不到合适的地方来做这件事。是否有一些中间件在开发模式下将请求路由到 /assets/* 到 /app/assets/ /,在那个阶段加入是否合适?

欢迎大家提出意见。

4

1 回答 1

2

在阅读了 sprockets 源代码和一些 actionpack sprockets 的东西之后,我一直在努力解决这个问题,我想出了这种方法。只需将它放在 app/assets/javascripts/assets.js.erb 或类似的地方。它使用 Sprockets::Environment 中的 each_logical_path 方法迭代所有资产文件,然后使用该路径实例化一个资产对象。根据是否为您的 rails env 启用资产摘要,返回正确的资产路径。

<%
  manifest = {}
  app = Rails.application
  env = app.assets
  env.each_logical_path do |logical_path|
    if File.basename(logical_path)[/[^\.]+/, 0] == 'index'
      logical_path.sub!(/\/index\./, '.')
    end

    # grabbed from Sprockets::Environment#find_asset
    pathname = Pathname.new(logical_path)
    if pathname.absolute?
      return unless stat(pathname)
      logical_path = attributes_for(pathname).logical_path
    else
      begin
        pathname = resolve(logical_path)
      rescue Sprockets::FileNotFound
        return nil
      end
    end

    asset = Sprockets::Asset.new(env, logical_path, pathname)
    manifest[logical_path] = app.config.assets.digest ? asset.digest_path : asset.logical_path
  end
%>

!function(window, document, undefined){

  var assets = <%= ActiveSupport::JSON.encode(manifest) %>;

  var asset_path = function(path){
    if(assets.hasOwnProperty(path)){
      return '/assets/' + assets[path];
    }
    else{
      throw Error('missing asset: ' + path);
    }
  };
  window.asset_path = asset_path;
  window.asset_url = function(path){ return window.location.protocol + '//' + window.location.host + asset_path(path); };
}(window, document);

这仍然需要一些工作,但我认为我在正确的轨道上。

于 2012-06-22T16:49:25.677 回答