Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are my Rails assets getting precompiled twice?

I've noticed my assets seem to get compiled twice, which considerably slows down my deployment, as this step is the most time consuming part:

~/projects/rewportal(mapwidget ✔) rake assets:precompile
/home/ruy/.rvm/rubies/ruby-1.9.3-p194/bin/ruby /home/ruy/.rvm/gems/ruby-1.9.3-p194@rewportal/bin/rake assets:precompile:all RAILS_ENV=production RAILS_GROUPS=assets
AssetSync: using /home/ruy/projects/rewportal/config/initializers/asset_sync.rb
AssetSync: using /home/ruy/projects/rewportal/config/initializers/asset_sync.rb
AssetSync: Syncing.
Using: Directory Search of /home/ruy/projects/rewportal/public/assets
Uploading: assets/application-5170f52c1dd49cb382d5135bee01d75e.js
[...]
Fetching files to flag for delete
Flagging 8 file(s) for deletion
Deleting: assets/active_admin-4ce46d089d4b0080e87c9abcb6fa6c97.css
[...]
AssetSync: Done.

It this normal?

When I precompile to other environments (non-production), I can see the detailed compilation of each asset twice:

~/projects/rewportal(mapwidget ✔) rake RAILS_ENV=qa assets:precompile --trace
** Invoke assets:precompile (first_time)
** Execute assets:precompile
/home/ruy/.rvm/rubies/ruby-1.9.3-p194/bin/ruby /home/ruy/.rvm/gems/ruby-1.9.3-p194@rewportal/bin/rake assets:precompile:all RAILS_ENV=qa RAILS_GROUPS=assets --trace
** Invoke assets:precompile:all (first_time)
** Execute assets:precompile:all
** Invoke assets:precompile:primary (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
AssetSync: using /home/ruy/projects/rewportal/config/initializers/asset_sync.rb
** Invoke tmp:cache:clear (first_time)
** Execute tmp:cache:clear
** Execute assets:precompile:primary
Compiled gmaps4rails/gmaps4rails.base.js  (141ms)  (pid 8480)
Compiled gmaps4rails/gmaps4rails.googlemaps.js  (148ms)  (pid 8480)
[...]
Compiled active_admin.css  (1299ms)  (pid 8480)
Compiled active_admin/print.css  (113ms)  (pid 8480)
** Invoke assets:precompile:nondigest (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
AssetSync: using /home/ruy/projects/rewportal/config/initializers/asset_sync.rb
** Invoke tmp:cache:clear (first_time)
** Execute tmp:cache:clear
** Execute assets:precompile:nondigest
Compiled gmaps4rails/gmaps4rails.base.js  (133ms)  (pid 8480)
Compiled gmaps4rails/gmaps4rails.googlemaps.js  (133ms)  (pid 8480)
[...]
Compiled active_admin.css  (1290ms)  (pid 8480)
Compiled active_admin/print.css  (116ms)  (pid 8480)
AssetSync: Syncing.
Using: Directory Search of /home/ruy/projects/rewportal/public/assets
Uploading: assets/active_admin-d05b61ab8366b74eabc9074d3e60fe82.css.gz
[...]
Fetching files to flag for delete
Flagging 6 file(s) for deletion
Deleting: assets/active_admin-ec90e7d9a9f45f14d1387f58fa1452b4.css
[...]
AssetSync: Done.

My application.rb has the following:

config.assets.precompile += %w( active_admin/print.css active_admin.css active_admin.js admin.js admin.css html5shiv.js )

Ideas?

like image 243
Ruy Diaz Avatar asked Mar 13 '13 19:03

Ruy Diaz


People also ask

How do you Precompile Rails assets?

To compile your assets locally, run the assets:precompile task locally on your app. Make sure to use the production environment so that the production version of your assets are generated. A public/assets directory will be created. Inside this directory you'll find a manifest.

What does bundle exec rake assets Precompile do?

4.1 Precompiling Assets. Rails comes bundled with a rake task to compile the asset manifests and other files in the pipeline to the disk. Compiled assets are written to the location specified in config.

How does Rails asset pipeline work?

The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages such as CoffeeScript, Sass and ERB. Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets.


2 Answers

Rails 3 by default compiles once to generate fingerprinted assets, and once to generate non-fingerprinted assets (the fingerprinted ones have the MD5 hash in the filename).

You can use the turbo-sprockets-rails3 gem to create both from one compilation.

In Rails 4, this functionality was extracted into the sprockets-rails gem and the behavior was changed, so the double compilation does not happen in Rails 4.

like image 144
carols10cents Avatar answered Sep 28 '22 22:09

carols10cents


Are you using capistrano? If so, you can try to compile your assets locally, and then upload to server, with a task like this

namespace :deploy do
  namespace :assets do
    desc "Precompile assets on local machine and upload them to the server."
    task :precompile, roles: :web, except: {no_release: true} do
      run_locally "bundle exec rake assets:precompile"
      find_servers_for_task(current_task).each do |server|
        run_locally "rsync -vr --exclude='.DS_Store' public/assets #{user}@#{server.host}:#{shared_path}/"
      end
    end
  end
end
like image 40
Luiz E. Avatar answered Sep 28 '22 21:09

Luiz E.