Evgenii
Evgenii

Reputation: 37339

rake assets:precompile is slow

The command "rake assets:precompile" works very slow for me. Especially on my Amazon EC2 Micro production server which does not have a lot of processor resources. On EC2 I have to wait 1 minute or more during each deployment just for this precompile task alone. Is there a way to make it faster?

Previously I used Jammit to compress/minify css and js. Jammit worked nearly 10 times faster on the same web site and servers.

Upvotes: 26

Views: 14112

Answers (3)

ndbroadbent
ndbroadbent

Reputation: 13803

If you don't need to load the Rails environment, you should disable that with:

config.assets.initialize_on_precompile = false

EDIT: I've just written a gem to solve this problem, called turbo-sprockets-rails3. It speeds up your assets:precompile by only recompiling changed files, and only compiling once to generate all assets.

It would be awesome if you could help me test out the turbo-sprockets-rails3 gem, and let me know if you have any problems.

Upvotes: 30

mcasimir
mcasimir

Reputation: 678

My solution is to exclude application.js .css and any other application related assets from from precompilation. So that i can use rake assets:precompile once to precompile engine related assets only.

Then on each deploy i use a simple rake task to build any application related assets and merge them into manifest.yml:

namespace :assets do
  task :precompile_application_only => :environment do
    require 'sprockets'

    # workaround used also by native assets:precompile:all to load sprockets hooks 
    _ = ActionView::Base

    # ==============================================
    # = Read configuration from Rails / assets.yml =
    # ==============================================

    env           = Rails.application.assets
    target        = File.join(::Rails.public_path, Rails.application.config.assets.prefix)
    assets        = YAML.load_file(Rails.root.join('config', 'assets.yml'))
    manifest_path = Rails.root.join(target, 'manifest.yml')
    digest        = !!Rails.application.config.assets.digest
    manifest      = digest


    # =======================
    # = Old manifest backup =
    # =======================

    manifest_old = File.exists?(manifest_path) ? YAML.load_file(manifest_path) : {}

    # ==================
    # = Compile assets =
    # ==================

    compiler = Sprockets::StaticCompiler.new(env,
                                            target,
                                            assets,
                                            :digest => digest,
                                            :manifest => manifest)
    compiler.compile

    # ===================================
    # = Merge new manifest into old one =
    # ===================================

    manifest_new  = File.exists?(manifest_path) ? YAML.load_file(manifest_path) : {}

    File.open(manifest_path, 'w') do |out|
       YAML.dump(manifest_old.merge(manifest_new), out)
    end

  end
end

To specify which assets to compile i use a YAML configuration file (config/assets.yml):

eg.

---
- site/site.css
- admin/admin.css
- site/site.js
- admin/admin.js

Upvotes: 1

Richard Hulse
Richard Hulse

Reputation: 10493

There is a bug in Rails 3.1.0 that includes too many files in the precompile process. This could be the reason for the slowness if you have many assets js and css assets.

The other is that Sprockets (the gem doing the compilation) is more complex and has to allow for more options - scss, coffeescript and erb. Because of this I suspect it will be slower doing just concatenation and minification.

As suggested, you could precompile the files before deploying them if this is still an issue.

Upvotes: 10

Related Questions