Rails asset precompile and Heroku Pipelines

798 Views Asked by At

I'm deploying my Rails application using Heroku Pipelines (it's been reliable and fast).

However, because assets are only precompiled once, during their deployment to staging, the promoted CSS assets in production all contain references to images and fonts on the staging CDN.

// Precompiled Source:
background-image: image-url('background.png');
// Compfiled Result:
background-image: url('https://stagingcdn.domain.com/assets/backgroundXXXXXXX.png');

Is there a way to configure Rails to output relative paths for the asset-url() helpers, rather than the absolute path containing the asset_hosts domain?

Or some form of a post-promotion phase where I can run precompile again for production deployments? Looking through docs from Herkou hasn't suggested much, apart from switching to the asset-sync gem, which they actively discourage elsewhere.

Appreciate any experience or ideas.

2

There are 2 best solutions below

2
On

You can precompile again on a production app by doing the following:

heroku run RAILS_ENV=production bundle exec rake assets:clobber - To purge the existing compiled values/names in the "public" folder.

heroku run RAILS_ENV=production bundle exec rake assets:precompile - To compile everything again.

You will most likely need to do this every time you commit new assets to your Heroku server.

However, you shouldn't run these on your local machine (development) if you are navigating to assets via their name in the "public" folder on your production app. It will change their "public" names when you compile them again on your production machine.

0
On

I had the same issue recently and solved it by clearing the asset_host before assets:precompile is run.

This way, instead of it generating references like https://cdn.mysite.com/assets/cat-abc123.jpg, it will generate them like, /assets/cat-abc123.jpg. When you access the stylesheet through https://cdn.mysite.com, the absolute path will resolve relative to the CDN, regardless of whether it is your staging or production one.

I achieved this putting the the following in my Rakefile after load_tasks has been called:

task :clear_asset_host do
  Rails.configuration.action_controller.asset_host = nil
end

Rake::Task["assets:precompile"].enhance [:clear_asset_host]