Using Webpack with Jekyll

I recently re-wrote this site to use webpack for asset bundling. Most of it was pretty simple — webpack is excellent — but the final problem was how to incorporate the code into the live website. Since this site is hosted on CloudFront and uses fairly aggressive caching, I needed to include hashes in the filenames of the bundled JS/CSS, so nobody pulls outdated CSS/JS when visiting an updated version of the site.

It turns out that it was fairly simple to place a hook into webpack.config.js in order to include the hash of the latest webpack build as a variable in Jekyll.

I simply created a file called _data/webpack.yml. Initially I added the new hash to _config.yml, but jekyll will not re-load _config.yml changes, meaning a _data file is a better option for development.

Then I added the following to the plugins field of webpack.config.js:

function() {
  this.plugin("done", function(stats) {
    fs.writeFileSync(path.join(__dirname, "_data", "webpack.yml"),
      'hash: "'+stats.hash+'"');

Which overwrites the file with the new hash when webpack is done. Then I added the hash to the name of the webpack files:

output: {
  path: path.resolve(__dirname, 'assets'),
  filename: 'bundle-[name]-[hash].js'

And updated my layouts to use site.data.webpack.hash to refer to the generated files.

Update 5/5/17

I’ve just added a microblog to this site that uses multiple entry points. To do that, I added them to the WebPack config in the normal way:

entry: { 
  main: "./assets/entry.js",
  microblog: "./assets/entry-microblog.js"

Then, in the default.html layout, I used the following:

<script src="/assets/webpack/bundle-{% raw %}{% if page.jsentry %}{{page.jsentry}}{% else %}main{% endif %}-{{site.data.webpack.hash}}{% endraw %}.js"></script>

And then pages with specific JS code have the following sort of metadata:

jsentry: "microblog"

I also use extract-text-webpack-plugin to separate the CSS out.

It’s a little verbose, but results in a better browsing experience for the user.