Assets

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.

  1. use webpack assets in Rails
  2. 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:syncstep 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.