the build process (including
assets:precompile) is not run during a pipeline promotion.
So any URLs or other environment-specific variables will get “baked in” during the staging build and will go live along with the new slug when it is promoted.
The Ruby buildpack runs the rake assets:clean command during a build to remove older assets. By default, this keeps the 3 most recent builds and prevents the app size from growing nonstop.
Overall there are two options broad options
- Use a CDN with asset_host like CloudFront. Use a different CDN for production and staging, but assets referenced from inside of your production assets will have full urls that point to the staging CDN. This works most of the time unless you’re aggressively revising assets on your staging server which would clear an old asset out and make it not available. You can do this on the CDN with one distribution for your staging server and another distribution for your production server. Both of these are configurable via env vars. When you deploy, your assets get compiled with any internal links pointing at the staging CDN and any links that are generated directly as the view is rendering will be served from the production CDN. In this setup, the staging CDN always serves assets from the staging server. The production CDN points to the production app. It will serve assets from the production app on all assets that your app renders directly into the html of a page. However, if that asset references another asset (for example a css file pointing to an image inside of the css) then that “internal” asset will be rendered from the staging CDN as that asset was compiled on the staging app in the pipeline.
2. Use a CDN like Cloudflare, don’t set any asset_host and let DNS caching do it’s thing. The problem here is if you’ve referenced any assets as an absolute value, such as in your JS. There are ways to get around this as you’ve said, buy using data- tags in your HTML but that would require you to potentially re-architect large parts of the whole app.
Another solution is using asset sync, but this is strongly discouraged on Heroku.