42

私はRails 3.2プロジェクトに取り組んでおり、プロジェクトが大規模であるとは考えていませんが、アセットはここ数か月でかなり増加しました。アセットは JS (コーヒー スクリプトなし) と SASS ファイルで構成されます。かなりの数の画像がありますが、初期の頃から数が減っているため、重要な要素ではないと思います. 約 12 個のライブラリがあり、ほとんどが小規模で、最大のものは Jquery UI JS です。デプロイは Capistrano を介して行われ、ステージングへのデプロイは本番環境へのデプロイよりも大幅に高速であることが明らかになり始めました。さまざまなサーバーとネットワークの影響に関する要因を回避しながら説明するために、ラップトップで次の 3 つのコマンドを次のように順番に実行しました。

$ time RAILS_ENV=production bundle exec rake assets:precompile
^Crake aborted!
[Note I aborted this run as I felt it was getting stupidly long...]
real    52m33.656s
user    50m48.993s
sys 1m42.165s

$ time RAILS_ENV=staging bundle exec rake assets:precompile
real    0m41.685s
user    0m38.808s
sys 0m2.803s

$ time RAILS_ENV=development bundle exec rake assets:precompile
real    0m12.157s
user    0m10.567s
sys 0m1.531s

だから私は頭を悩ませています。さまざまな環境の間になぜこれほど大きな違いがあるのでしょうか? 開発とステージングのギャップは理解できますが、ステージングと本番の構成は同じです。(実動コンパイルは約 2 時間後に完了します!)

最終的にはプリコンパイルが高速化されますが、これを達成するには、常にどこに行くのか、Rails 環境間に大きな違いがある理由を理解する必要があります。さまざまなコンプレッサーなどの使用に関する他の投稿を見たことがありますが、これらの rake タスクをデバッグして時間が費やされている場所を特定し、どの設定がそのような劇的な違いを引き起こしている可能性があるかを特定する方法に関する情報を見つけることができません。

I don't know what additional information people may need so will update if and when comments ask. TIA

Update: additional information supplied below

config/environments/production.rb and config/environments/staging.rb (they're exactly the same):

MyRailsApp::Application.configure do
  # Code is not reloaded between requests
  config.cache_classes = true

  # Full error reports are disabled and caching is turned on
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true

  # Disable Rails's static asset server (Apache or nginx will already do this)
  config.serve_static_assets = true
  config.static_cache_control = "public, max-age=31536000"
  config.action_controller.asset_host = "//#{MyRailsApp::CONFIG[:cdn]}"

  # Compress JavaScripts and CSS
  config.assets.compress = true

  # Don't fallback to assets pipeline if a precompiled asset is missed
  config.assets.compile = false

  # Generate digests for assets URLs
  config.assets.digest = true

  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  # the I18n.default_locale when a translation can not be found)
  config.i18n.fallbacks = true

  # Send deprecation notices to registered listeners
  config.active_support.deprecation = :notify
end

The base config/application.rb is:

require File.expand_path('../boot', __FILE__)

require 'rails/all'

if defined?(Bundler)
  # If you precompile assets before deploying to production, use this line
  Bundler.require(*Rails.groups(:assets => %w(development test)))
  # If you want your assets lazily compiled in production, use this line
  # Bundler.require(:default, :assets, Rails.env)
end
module MyRailsApp
  CONFIG = YAML.load_file(File.join(File.dirname(__FILE__), 'config.yml'))[Rails.env]

  class Application < Rails::Application

    # Custom directories with classes and modules you want to be autoloadable.
    config.autoload_paths += %W(#{config.root}/lib)
    config.autoload_paths += %W(#{config.root}/app/workers)

    # Configure the default encoding used in templates for Ruby 1.9.
    config.encoding = "utf-8"

    # Configure sensitive parameters which will be filtered from the log file.
    config.filter_parameters += [:password]

    # Enable the asset pipeline
    config.assets.enabled = true

    # Stop precompile from looking for the database
    config.assets.initialize_on_precompile = false

    # Version of your assets, change this if you want to expire all your assets
    config.assets.version = '1.0'

    # Fix fonts in assets pipeline
    # http://stackoverflow.com/questions/6510006/add-a-new-asset-path-in-rails-3-1
    config.assets.paths << Rails.root.join('app','assets','fonts')

    config.middleware.insert 0, 'Rack::Cache', {
      :verbose     => true,
      :metastore   => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/meta"),
      :entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
    } # unless Rails.env.production?  ## uncomment this 'unless' in Rails 3.1,
                                      ## because it already inserts Rack::Cache in production

    config.middleware.insert_after 'Rack::Cache', 'Dragonfly::Middleware', :images

    config.action_mailer.default_url_options = { :host => CONFIG[:email][:host] }
    config.action_mailer.asset_host = 'http://' + CONFIG[:email][:host]
  end
end

Gem file:

source 'http://rubygems.org'

gem 'rails', '3.2.13'   
gem 'mysql2'
gem 'dragonfly', '>= 0.9.14'
gem 'rack-cache', :require => 'rack/cache'
gem 'will_paginate'
gem 'dynamic_form'
gem 'amazon_product' # for looking up Amazon ASIN codes of books
gem 'geoip'
gem 'mobile-fu'
gem 'airbrake'
gem 'newrelic_rpm'
gem 'bartt-ssl_requirement', '~>1.4.0', :require => 'ssl_requirement'
gem 'dalli' # memcache for api_cache
gem 'api_cache'
gem 'daemons'
gem 'delayed_job_active_record'
gem 'attr_encrypted'
gem 'rest-client'
gem 'json', '>= 1.7.7'
gem 'carrierwave' # simplify file uploads
gem 'net-scp'

# Gems used only for assets and not required
# in production environments by default.
group :assets do
  gem 'therubyracer'
  gem 'sass-rails',   '~> 3.2.3'
  gem 'compass', '~> 0.12.alpha'
  gem 'uglifier', '>= 1.0.3'
  gem 'jquery-fileupload-rails'
end

gem 'jquery-rails'
gem 'api_bee', :git => 'git://github.com/ismasan/ApiBee.git', :ref => '3cff959fea5963cf46b3d5730d68927cebcc59a8'
gem 'httparty', '>= 0.10.2'
gem 'twitter'

# Auth providers
gem 'omniauth-facebook'
gem 'omniauth-twitter'
gem 'omniauth-google-oauth2'
gem 'omniauth-identity'
gem 'omniauth-readmill'
gem 'bcrypt-ruby', "~> 3.0.0" # required for omniauth-identity
gem 'mail_view'

# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'

# Deploy with Capistrano
group :development do
  gem 'capistrano'
  gem 'capistrano-ext'
  gem 'capistrano_colors'
  gem 'rvm-capistrano'

  # requirement for Hoof, Linux equivalent of Pow
  gem 'unicorn'
end

group :test, :development do  
  gem 'rspec-rails'
  gem 'pry'
  gem 'pry-rails'
end

group :test do
  gem 'factory_girl_rails'
  gem 'capybara'
  gem 'cucumber-rails'
  gem 'database_cleaner'
  gem 'launchy'
  gem 'ruby-debug19'
  # Pretty printed test output
  gem 'shoulda-matchers'
  gem 'simplecov', :require => false
  gem 'email_spec'
  gem 'show_me_the_cookies'
  gem 'vcr'
  gem 'webmock', '1.6'
end
4

3 に答える 3

36

これであなたの質問に完全に答えることはできないかもしれませんが、十分な出発点だと思います。ご覧のとおり、正確な答えは個々のアプリケーションや gem のバージョンなどによって異なります。

そう。ご存知のように、Rails はアセット関連の作業のために Sprockets と呼ばれるライブラリを使用します。これは、Rails の新しいバージョンでは、Railtie として Rails にフックされていると思います。アセット マニフェストの参照、ファイルのロード、圧縮、コンパイルされたアセットへの適切な名前の付与などを実行できる Sprockets の「環境」を初期化します。

デフォルトでは、 はSprockets::EnvironmentそのアクティビティをSTDERRのログ レベルでログに記録しますがFATAL、これはこれらの状況ではあまり役に立ちません。幸いなことに、Sprockets::Environment(現在2.2.2) には、初期化子を使用して Rails 経由でパッチできる書き込み可能な logger 属性があります。


だから、ここに私が提案するものがあります:

config/initializers、のようなファイルを作成しますasset_logging.rb。その中に、以下を入れてください:

Rails.application.config.assets.logger = Logger.new($stdout)

これにより、デフォルトのロガーが、より多くの情報を吐き出すロガーで上書きされSTDOUTます。この設定が完了したら、アセットの事前コンパイル タスクを実行します。

rake RAILS_ENV=production assets:precompile

次のような、もう少し興味深い出力が表示されるはずです。

...
Compiled jquery.ui.core.js  (0ms)  (pid 66524)
Compiled jquery.ui.widget.js  (0ms)  (pid 66524)
Compiled jquery.ui.accordion.js  (10ms)  (pid 66524)
...

しかし、最終的には、最終的な答えは次の要素に依存します。

  • このアセットのログをどの程度「深く」したいか
  • 使用しているレール、スプロケットなどの特定のバージョン
  • そして途中で見つけたもの

すでに学んだように、Rake タスク レベルで、または Rails レベルでさえ、ログ スペランキングは多くの情報を提供しません。また、Sprockets 自体を冗長にしても (上記を参照)、それほど多くのことはわかりません。

Sprockets よりも深く掘り下げたい場合は、おそらく、Sprockets が忠実に連結してアセット パイプラインを機能させるさまざまなエンジンとプロセッサにモンキー パッチを適用できます。たとえば、次のコンポーネントのロギング機能を調べることができます。

  • Sass::Engine(SASS を CSS に変換)
  • Uglifier(JavaScript 圧縮ラッパー)
  • ExecJS(Ruby で JavaScript を実行します。Sprockets と Ugliifier の両方に依存します)
  • therubyracer(Ruby に埋め込まれた V8。 で使用ExecJS)

しかし、それはすべて「読者の演習」として残しておきます。特効薬があるなら、ぜひ知りたいです!

于 2013-10-15T01:16:39.600 に答える