11

Rails 3 には rake assets:precompile:nodigest タスクがあり、アセットをコンパイルして /public/assets ディレクトリにダイジェスト部分なしで書き込んでいました。Rails 4 ではこれが削除され、デフォルトですべてのアセットがダイジェストのみでプリコンパイルされます。さまざまな理由から、一部のアセットの消化されていないバージョンも必要です。古い動作を元に戻す簡単な方法はありますか?

4

6 に答える 6

25

Rails 4.0.0で使用されている のバージョンはsprockets-rails、非ダイジェスト アセットをサポートしなくなりました。

sprocket-rails の Readmeごと:

ダイジェスト ファイル名のみをコンパイルします。静的な非ダイジェスト アセットは、単純に公開する必要があります

したがって、静的にする必要があるアセットは、手動でフォルダーに入れることができpublicます。SCSS ファイルなどのコンパイル済みアセットをコピーする必要がある場合は、この rake タスクが役立ちます ( source ):

task non_digested: :environment do
  assets = Dir.glob(File.join(Rails.root, 'public/assets/**/*'))
  regex = /(-{1}[a-z0-9]{32}*\.{1}){1}/
  assets.each do |file|
    next if File.directory?(file) || file !~ regex

    source = file.split('/')
    source.push(source.pop.gsub(regex, '.'))

    non_digested = File.join(source)
    FileUtils.cp(file, non_digested)
  end
end
于 2013-07-08T21:18:11.863 に答える
8

これを行うための gem もあります。やや挑発的な名前のnon-stupid-digest-assetsです。

gem "non-stupid-digest-assets"
于 2014-09-25T22:13:26.640 に答える
4

最良の回答が示唆しているように、急いでいない場合は、最初に問題を読んで背景のストーリーを完全に理解することをお勧めします. https://github.com/rails/sprockets-rails/issues/49#issuecomment-24837265というアイデアが一番気に入っています。

以下は私の個人的な見解です。基本的には、上記の回答からコードを取得しました。私の場合、未消化にしたい2つのファイル、widget.jsとwidget.cssしかありません。そのため、sprockets メソッドを使用して消化されたファイルを見つけ、パブリック フォルダーにシンボリック リンクします。

# config/environments/production.rb
config.assets.precompile += %w[v1/widget.js v1/widget.css]

# lib/tasks/assets.rake
namespace :assets do
  desc 'symlink digested widget-xxx.js and widget-xxx.css to widget.js and widget.css'
  task symlink_widget: :environment do
    next if Rails.env.development? || Rails.env.test?

    digested_files = []
    # e.g. /webapps/myapp/public/assets
    assets_path = File.join(Rails.root, 'public', Rails.configuration.assets.prefix)

    %w(v1/widget.js v1/widget.css).each do |asset|
      # e.g. 'v1/widget-b61b9eaaa5ef0d92bd537213138eb0c9.js'
      logical_path = Rails.application.assets.find_asset(asset).digest_path
      digested_files << File.join(assets_path, logical_path)
    end

    fingerprint_regex = /(-{1}[a-z0-9]{32}*\.{1}){1}/
    digested_files.each do |file|
      next unless file =~ fingerprint_regex

      # remove fingerprint & '/assets' from file path
      non_digested = file.gsub(fingerprint_regex, '.')
                         .gsub(Rails.configuration.assets.prefix, '')

      puts "Symlinking #{file} to #{non_digested}"
      system "ln -nfs #{file} #{non_digested}"
    end
  end
end
于 2014-01-27T00:45:36.547 に答える
1

Dylan Markowに感謝します。私は彼の答えに従いますが、Capistrano を使用する場合、アセットにいくつかのバージョン (application-0a*.css、application-9c*.css など) があることがわかりました。未消化。ロジックは次のとおりです。

namespace :my_app do
  task non_digested: :environment do
    assets = Dir.glob(File.join(Rails.root, 'public/assets/**/*'))
    regex = /(?<!manifest)(-{1}[a-z0-9]{32}\.{1}){1}/
    candidates = {}

    # gather files info
    assets.each do |file|
      next if File.directory?(file) || file !~ regex

      source = file.split('/')
      source.push(source.pop.gsub(regex, '.'))
      non_digested = File.join(source)
      file_mtime = File.stat(file).mtime
      c = candidates[non_digested]
      if c.blank? || file_mtime > c[:mtime]
        candidates[non_digested] = {orig: file, mtime: file_mtime}
      end
    end

    # genearate
    for non_digested, val in candidates do
      FileUtils.cp(val[:orig], non_digested)
    end
  end
end

Rake::Task['assets:precompile'].enhance do
  Rake::Task['my_app:non_digested'].invoke
end

また、907th の正規表現コメントを適用し、プリコンパイル後にこのタスクを実行させるフックを追加しました。

于 2016-06-24T02:20:41.783 に答える
1

利用可能なすべてのオプションの私の膨大な分析はここにあります:

https://bibwild.wordpress.com/2014/10/02/non-digested-asset-names-in-rails-4-your-options/

カスタム レーキ タスクを追加することにしました。カスタム構成を使用して、消化されていないバージョンとして生成する特定のアセットを決定し、Sprockets マニフェストを使用して、消化されたアセットを見つけて、消化されていない名前でコピーします。

https://github.com/team-umlaut/umlaut/blob/5edcc609389edf833a79caa6f3ef92982312f0c5/lib/tasks/umlaut_asset_compile.rake

# Rails4 doesn't create un-fingerprinted assets anymore, but we
# need a couple for umlaut's API. Let's try to hook in and make
# symlinks. 
#
# list of what file(globs) need non-digest-named copies is kept in
#     Umlaut::Engine.config.non_digest_named_assets
# defined in lib/umlaut.rb, but app can modify it if desired. 

require 'umlaut'
require 'pathname'


# Every time assets:precompile is called, trigger umlaut:create_non_digest_assets afterwards. 
Rake::Task["assets:precompile"].enhance do
  Rake::Task["umlaut:create_non_digest_assets"].invoke
end

namespace :umlaut do 

  # This seems to be basically how ordinary asset precompile
  # is logging, ugh. 
  logger = Logger.new($stderr)  

  # Based on suggestion at https://github.com/rails/sprockets-rails/issues/49#issuecomment-20535134
  # but limited to files in umlaut's namespaced asset directories. 
  task :create_non_digest_assets => :"assets:environment"  do    
    manifest_path = Dir.glob(File.join(Rails.root, 'public/assets/manifest-*.json')).first
    manifest_data = JSON.load(File.new(manifest_path))

    manifest_data["assets"].each do |logical_path, digested_path|
      logical_pathname = Pathname.new logical_path

      if Umlaut::Engine.config.non_digest_named_assets.any? {|testpath| logical_pathname.fnmatch?(testpath, File::FNM_PATHNAME) }
        full_digested_path    = File.join(Rails.root, 'public/assets', digested_path)
        full_nondigested_path = File.join(Rails.root, 'public/assets', logical_path)

        logger.info "(Umlaut) Copying to #{full_nondigested_path}"

        # Use FileUtils.copy_file with true third argument to copy
        # file attributes (eg mtime) too, as opposed to FileUtils.cp
        # Making symlnks with FileUtils.ln_s would be another option, not
        # sure if it would have unexpected issues. 
        FileUtils.copy_file full_digested_path, full_nondigested_path, true      
      end
    end

  end
end
于 2015-12-03T16:15:33.253 に答える