33

我希望预编译项目app/assets文件夹中的所有 CSS 和 JS 文件。我不想预编译 vendor/assets 或 lib/assets 中的所有内容,只需要根据需要预编译我的文件的依赖项。

我尝试了以下通配符设置,但它错误地预编译了所有内容。这会导致大量额外工作,甚至在使用 bootstrap-sass 时导致编译失败。

config.assets.precompile += ['*.js', '*.css']

我最好的选择是只处理我的文件app/assets?谢谢!

4

8 回答 8

23

config.assets.precompile = ['*.js', '*.css']

这将编译资产路径中的任何 JavaScript 或 CSS,无论目录深度如何。通过这个答案找到。

于 2013-01-31T07:56:25.673 回答
20

由于 sprockets 使用不包括底层未编译资源所在位置的逻辑路径,因此这项任务变得更加困难。

假设我的项目有 JS 文件“/app/assets/javascripts/foo/bar.js.coffee”。

sprockets 编译器将首先确定输出文件扩展名,在本例中为“.js”,然后评估是否编译逻辑路径“foo/bar.js”。未编译的资源可能位于“app/assets/javascripts”、“vendor/assets/javascripts”、“lib/assets/javascripts”或 gem 中,因此无法根据逻辑路径包含/排除特定文件独自的。

要确定底层资源的位置,我认为有必要询问 sprockets 环境(可通过对象 Rails.application.assets 获得)以在给定逻辑路径的情况下解析资源的真实路径。

这是我正在使用的解决方案。我对 Ruby 很陌生,所以这不是最优雅的代码:

# In production.rb
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    app_assets_path = Rails.root.join('app', 'assets').to_path
    if full_path.starts_with? app_assets_path
      puts "including asset: " + full_path
      true
    else
      puts "excluding asset: " + full_path
      false
    end
  else
    false
  end
}

对于 sprockets > 3.0,这在生产环境中不起作用,因为 Rails.application.assets 将为 nil(假设默认值:config.assets.compile = false)。

要解决此问题,请将full_path分配替换为:

@assets ||= Rails.application.assets || Sprockets::Railtie.build_environment(Rails.application)
full_path = @assets.resolve(path)

另见:https ://github.com/rails/sprockets-rails/issues/237

于 2012-04-11T16:39:16.980 回答
18

对 techpeace 的回答稍作调整:

config.assets.precompile = ['*.js', '*.css', '**/*.js', '**/*.css']

我会在他的回答中添加评论,但我还没有足够的声誉。给我一个upvote,我会在那里!

注意:这也将预编译通过 ruby​​gems 包含的所有 CSS/JavaScript。

于 2013-09-24T21:50:05.500 回答
7

我在rails代码中找到了这个:

@assets.precompile               = [ Proc.new{ |path| !File.extname(path).in?(['.js', '.css']) },
                                     /(?:\/|\\|\A)application\.(css|js)$/ ]

这是由rails指南支持的:

编译文件的默认匹配器包括 application.js、application.css 和所有非 JS/CSS 文件

如果使用 ,则不会重置此默认值+=,因此您需要使用 a=而不是覆盖它+=。请注意,显然,您可以将 Proc 或正则表达式传递给precompile扩展名。我相信,如果您只想预编译顶级目录中的文件,则必须创建一个正则表达式,例如:

config.assets.precompile = [ /\A[^\/\\]+\.(ccs|js)$/i ]
于 2012-04-11T04:06:48.107 回答
6

我在 2017 年重温这篇文章。

我们的产品仍然大量使用 RoR,我们一直在通过Rails.application.config.assets.precompile添加新模块来不断修改我们的预编译配置。最近我试图通过添加一个正则表达式模式来优化它,我发现以下 glob 模式有效:

Rails.application.config.assets.precompile += %w(**/bundle/*.js)

但是我仍然需要排除某些模块,所以我努力使用正则表达式而不是 glob。

在我查看 sprockets 源代码:https ://github.com/rails/sprockets-rails/blob/master/lib/sprockets/railtie.rb#L108 之前,我发现他们已经在使用正则表达式:

app.config.assets.precompile +=
  [LOOSE_APP_ASSETS, /(?:\/|\\|\A)application\.(css|js)$/]

所以我把我的代码改成:

Rails.application.config.assets.precompile +=
  [/^((?!my_excluded_module)\w)*\/bundle\/\w*\.js$/]

哪个效果很好。

于 2017-03-06T06:25:32.870 回答
3

这将获取所有.css .scss.js包括子目录中的所有文件。

js_prefix    = 'app/assets/javascripts/'
style_prefix = 'app/assets/stylesheets/'

javascripts = Dir["#{js_prefix}**/*.js"].map      { |x| x.gsub(js_prefix,    '') }
css         = Dir["#{style_prefix}**/*.css"].map  { |x| x.gsub(style_prefix, '') }
scss        = Dir["#{style_prefix}**/*.scss"].map { |x| x.gsub(style_prefix, '') }

Rails.application.config.assets.precompile = (javascripts + css + scss)
于 2016-03-16T10:23:38.613 回答
2

我希望编译来自 /app 和 /vendor 的所有资产,除了部分(名称以下划线 _ 开头)。所以这是我在 application.rb 中的条目版本:

config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    app_assets_path = Rails.root.join('app', 'assets').to_path
    vendor_assets_path = Rails.root.join('vendor', 'assets').to_path

    if ((full_path.starts_with? app_assets_path) || (full_path.starts_with? vendor_assets_path)) && (!path.starts_with? '_')
      puts "\t" + full_path.slice(Rails.root.to_path.size..-1)
      true
    else
      false
    end
  else
    false
  end
}

此外,它还输出为调试目的而编译的文件列表...

于 2013-03-21T22:41:45.977 回答
1

此片段包括所有 js/css 文件,不包括 gems,位于:app/assets、vendor/assetslib/assets下,除非它们是部分文件(例如“_file.sass”)。它还有一个策略来包含来自 Gems 的资产,这些资产并未包含在每个页面中。

    # These assets are from Gems which aren't included in every page.
    # So they must be included here
    # instead of in the application.js and css manifests.
    config.assets.precompile += %w(a-gem.css a-gem.js b-gem.js)

    # This block includes all js/css files, excluding gems,
    # under: app/assets, vendor/assets, lib/assets
    # unless they are partial files (e.g. "_file.sass")
    config.assets.precompile << Proc.new { |path|
      if path =~ /\.(css|js)\z/
        full_path = Rails.application.assets.resolve(path).to_path
        aps = %w( /app/assets /vendor/assets /lib/assets )
        if aps.any? {|ap| full_path.starts_with?("#{Rails.root}#{ap}")} &&
            !path.starts_with?('_')
          puts "\tIncluding: " + full_path.slice(Rails.root.to_path.size..-1)
          true
        else
          puts "\tExcluding: " + full_path
          false
        end
      else
        false
      end
    }

虽然,您可能不想这样做,因为您可能会两次预编译 gem 资产(基本上任何在 application.js 或 css 中已经 \=require'd 的东西)。此片段包括所有 js/css 文件,包括 gems,位于:app/assets、vendor/assetslib/assets下,除非它们是部分文件(例如“_file.sass”)

# This block includes all js/css files, including gems, 
# under: app/assets, vendor/assets, lib/assets
# and excluding partial files (e.g. "_file.sass")
config.assets.precompile << Proc.new { |path|
  if path =~ /\.(css|js)\z/
    full_path = Rails.application.assets.resolve(path).to_path
    asset_paths = %w( app/assets vendor/assets lib/assets)
    if (asset_paths.any? {|ap| full_path.include? ap}) && 
        !path.starts_with?('_')
      puts "\tIncluding: " + full_path
      true
    else
      puts "\tExcluding: " + full_path
      false
    end
  else
    false
  end
}
于 2013-10-16T20:29:13.853 回答