Using Rails with webpack generated assets
Our team started using webpack with Rails. Referencing/Sharing asset information from webpack to Rails is the problem being solved in this post. We want to use the webpack assets that are exposed in our Rails app. Not setting up a new plugin for uploading the generated assets would be a plus.
Our team used webpack
to compile javascript and related assets. (If you are trying to learn webpack, note that it has a very steep learning curve). Once you get the hang of it, you should be able to integrate/debug any other webpack plugin easily. I followed survivejs book.
After moving our Angular project including CSS, images and fixing compatibility issues. We had assets in Rails which we cannot move because they’d come from other gems. The application uses asset_sync
to sync data to CDN. The final step was to use webpack
assets in the existing rails app. For this we need to have a link point. The asset-manifest generated by sprockets has become our sync point.
We have a webpack-manifests file, rails manifest file. We need merge the webpack asset list into the Rails one so that we can do two things.
- use webpack assets in Rails
- upload webpack assets into the same storage service which is behind the CDN.
Here’s the code to get it done
Details
The rake task merges webpack asset files with rails before the asset:sync
step and after the assets:precompile
step. We have enhanced the rake task to achieve this (last few lines). sprockets
gem does not currently allow to add any custom files into the manifest. I raised another PR for allowing users customize the manifest file in sprockets.
The .manifest-random-string.json
file is a hash. The two keys are files
and assets
. asset_sync
gem uses the assets
key which has file => file-fingerprint
and uploads it. Uploads work great, but has a problem.
asset_sync
chooses to upload only rails fingerprinted files as ‘Cacheable’ in S3 (or other fog-storage adapters). I have made a code change to allow this to be customised. Now you can pass in cache_asset_regexps
to match the ones generated by webpack will solve the problem with ‘Cacheable’.
The regular expression usually matches these for webpack and rails
webpack assets -> vendor.[0-9a-f}{8}.js
rails_assets -> application.[0-9a-f]{32}.js
You can identify if this is working by checking the headers from the CDN for webpack specific files. Browser should not be re-requesting them on every browser reload.