« Previous Tutorial Next Tutorial »

Welcome back. We’ve got routing up and running, but we have a few problems. The expected one is that right now our code is repetitive and could be improved dramatically with a few simple tweaks. The second is that, oops, the Express wildcard we introduced in the last tutorial is causing a conflict with our Webpack hot-reloading server, and breaking hot reloading. This, for the record, is bad, and needs to be fixed before we do anything else.

In the process of researching the issue, I found a better way to handle Webpack/Express combos, using a terrific module called webpack-hot-middleware, which allows us to tie our Webpack server right into Express. This means no more conflicts, and it also means we don’t have to run a separate terminal window containing our Webpack server, since it will fire up when we launch Express with nodemon yarn start.

First thing we need to do is add two modules. Switch to a terminal window and type:

yarn add webpack-dev-middleware webpack-hot-middleware

Now we need to edit our webpack.config file, so open that up. Believe it or not, it’s going to end up shorter than it currently is, which is a minor miracle when it comes to Webpack! First, remove these two lines from the entry array:

    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/only-dev-server',

and replace them with the following:

    'react-hot-loader/babel',
    'webpack-hot-middleware/client',

Giving us the following:

  entry: [
    'react-hot-loader/patch',
    'react-hot-loader/babel',
    'webpack-hot-middleware/client',
    './index.jsx',
  ],

Change the output block to look like this:

  output: {
    filename: 'build.js',
    path: '/',
    publicPath: '/javascripts',
  },

The reason we don’t need the resolve(__dirname, 'public', 'javascripts'), line anymore is because we’re using a virtual server now, rather than writing out an actual JS file, so the physical location on the disk doesn’t actually matter to us (for now – we’ll need to address this before we move to production, but that’s a much later tutorial).

We can nuke the entire “devServer” block – Express is going to handle that for us. Just highlight and delete. Then move on to our plugins block, which gets one addition at the bottom:

    new webpack.NoEmitOnErrorsPlugin(),

That just makes errors a bit prettier in our console output, which is always nice.

OK, we’re done here. Save the file and open app.js. We’ve got some additions to make! Underneath line 14, which closes the const expressSession block, add the following:

const webpack = require('webpack');
const webpackConfig = require('./webpack.config');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

then, just below line 44, add the following:

// Webpack Server
const webpackCompiler = webpack(webpackConfig);
app.use(webpackDevMiddleware(webpackCompiler, {
  publicPath: webpackConfig.output.publicPath,
  stats: {
    colors: true,
    chunks: true,
    'errors-only': true,
  },
}));
app.use(webpackHotMiddleware(webpackCompiler, {
  log: console.log,
}));

You’ll get an ESLint warning about console logging, but it’s OK here because we’re logging to our Node console during development, rather than to the browser console for the actual production site.

Let’s go over this code. Here we’re creating a compiler that instantiates Webpack and ingests our config file, then adding it as Express Middleware (the stuff that gets used between request and response) to create a virtual JavaScript file that watches for changes and hot-reloads them.

Save this file. If you have a webpack server running, you can kill it. Then make sure your Express server has reset, and you should see it compile Webpack right in the server’s output. If so, good, but we need to do a few more things. First, open /views/index.ejs and change line 10,

<script src="http://localhost:8080/javascripts/build.js"></script>

to:

<script src="/javascripts/build.js"></script>

Then switch to your terminal window, cd to /public/javascripts, and delete your build.js file. If you miss this step, your dev server will not work and you will keep getting the same error in your browser’s console no matter what other changes you make, which will drive you crazy for way longer than it should before you finally figure it out. Not that I’m speaking from experience.

OK, we should be good. Let’s test our site and make sure it works. We need to hard-refresh since we’ve changed a bunch of stuff. Now let’s test hot-reloading by adding some extra text to HomePage.jsx and then saving the file … awesome! It should be working. If you’re having trouble, you can leave a comment and I’ll do my best to help out.

All right, we’ve done a substantial amount of work on this hot-reloading stuff, so let’s commit it to our repo. One more time for posterity, here’s how you do that. Fire up a terminal window, cd to your musiclist directory, and type the following:

git add -A
git commit -m "webpack and hot-reloading setup"
git push

From now on, I’m just going to remind you at the end of each tutorial to commit your work, and leave it up to you to do the above commands. Also, I’m gauging interest in a tutorial where I force a merge conflict and then walk you through resolving it. If that’s of interest, leave a comment letting me know!

See you in the next tutorial!

« Previous Tutorial Next Tutorial »