this is an example rails 5.1 app, created with the --webpack flag:
rails new rails-webpack-code-splitting --webpack -J -T -C -d=postgresql
you can see a diff of this app vs the initial scaffolding.
it features some tweaks to the webpack config to support the following things:
- explicit vendor and manifest chunks to improve caching of infrequently changed assets that are used on every page (lodash and cowsay, in this app)
- chunks for the loaded-on-demand scripts, date-picker and tooltip
- css loader and file loader, so i can load in styles and images that come with
installed dependencies (jquery ui in this case), note: these are loaded as js
and are added into the
<head>
as<style>
tags when the js executes - uglify js to deliver smaller payloads, and support tree shaking (webpacker pr for this here)
you can see it on heroku here:
https://fierce-everglades-99058.herokuapp.com
opening the "network" tab while clicking around will show you the following:
manifest-*.js
this is the webpack runtime files, and changes whenever any files are changed, because it includes the hashes for all the generated chunks. this is a tiny file that should probably be inlined but that seems tricky to bother with.
vendor-*.js
this is the "vendor bundle", e.g. libs that don't change often, and therefore should keep the same cache breaking hash even when application changes. it seems like tree-shaking does not affect these files though. i.e. all of lodash gets dragged in, making it a larger than necessary file.
if the vendor'd chunk is turned off, stuff is put into application instead. this causes application.js' size to jump from 6K to is 39K, but you don't have to load a 100K vendor file, so the tree shaking cuts off ~66K.
application-*.js
includes all the js that application.js
depends on, except the "loaded on demand" stuff (e.g. require.ensure ...
)
0-*.js
this, and the other {integer}-*.js
files are generated by webpack's commons
chunk plugin. this one happens to have the common dependencies between
date-picker.js and tooltip.js,
which is jquery, and the parts of jquery-ui that are used.
1-*.js
this happens to be tooltip.js and it's dependencies
that aren't already loaded in 0-*.js
.
2-*.js
this happens to be date-picker.js and it's dependencies
that aren't already loaded in 0-*.js
.
Note: almost all the package.json dependencies are moved out of devDependencies
,
and into dependencies
so that heroku is able to compile the app assets.
Pushing this to heroku results in the buildpacks being in the wrong order. You can correct them, and make sure all the ENV vars are set, with the commands below.
heroku create
heroku buildpacks:set heroku/nodejs --index 1
heroku buildpacks:set heroku/ruby --index 2
heroku config:set NODE_ENV=production WEBPACK_ENV=production RACK_ENV=production RAILS_ENV=production RAILS_LOG_TO_STDOUT=enabled RAILS_SERVE_STATIC_FILES=enabled
git push heroku master
with a vendor chunk
total 584
-rw-r--r-- 1 schpet staff 106K Feb 26 16:50 0-7a9b039224ba81bec731.js
-rw-r--r-- 1 schpet staff 21K Feb 26 16:50 1-0d651986ba6420fec25d.js
-rw-r--r-- 1 schpet staff 39K Feb 26 16:50 2-a4e9ef5ebeb657a7dbb3.js
-rw-r--r-- 1 schpet staff 6.3K Feb 26 16:50 application-e56d9424e57fe23cad6c.js
-rw-r--r-- 1 schpet staff 141B Feb 26 16:50 digests.json
-rw-r--r-- 1 schpet staff 1.5K Feb 26 16:50 manifest-d5431b62e5dbb0f9b7ad.js
drwxr-xr-x 3 schpet staff 102B Feb 26 16:50 node_modules
-rw-r--r-- 1 schpet staff 101K Feb 26 16:50 vendor-8b77afe5136e9241e6e7.js
without a vendor chunk, where tree shaking works:
total 432
-rw-r--r-- 1 schpet staff 106K Feb 26 16:52 0-415d10138f7df60ccf99.js
-rw-r--r-- 1 schpet staff 21K Feb 26 16:52 1-e5ecaeab4febc52c2df9.js
-rw-r--r-- 1 schpet staff 39K Feb 26 16:52 2-1c7d26b064e0ea833f15.js
-rw-r--r-- 1 schpet staff 39K Feb 26 16:52 application-8589f83f9bb3f8872cbd.js
-rw-r--r-- 1 schpet staff 53B Feb 26 16:52 digests.json
drwxr-xr-x 3 schpet staff 102B Feb 26 16:52 node_modules