« Previous Tutorial Next Tutorial »

All right, this is where the rubber meets the road. We’re going to get Webpack set up to do a basic compile of JSX, and then in the next tutorial we’re going to create two very simple JSX files with which we’ll initialize our React app and display it in the browser.

As it turns out, though, I missed a babel plugin we’re going to need in order to get everything up and running. Mea culpa! Switch to a terminal window or command prompt, and type the following:

yarn add babel-preset-env@1.6.1

We should be good to go at this point. Before we do anything else, let’s commit all of this to the develop branch of our git repo. As a reminder, here’s how to check if you’re in the right branch:

git branch

And here’s how to switch if you’re not:

git checkout develop

Then use these three lines to prep files for commit, commit them, and push them to the repo:

git add -A
git commit -m "API and testing setup."
git push

Once that’s done, it’s time to set up our Webpack config file. Switch to Sublime Text and, in the top level of your musiclist folder, create a file called webpack.config.js. This will contain our configuration for our react app.

Listen … Webpack is confusing. Like most powerful tools, it has a learning curve, and opening up a fully-established, hundred-line Webpack config for a commercial product and taking a look at it can be legitimately terrifying in the “oh, God, I’m literally never going to understand this” sense. At least, that’s how I felt the first time I looked at a Webpack config file – and I’m not kidding. My initial experience with React development was leaping into it head-first for a client, having never touched it before, and I spent the first two weeks suffering basically a prolonged, low-grade panic attack. It was overwhelming.

That’s why we’re going to do this bit-by-bit, instead of trying to set up everything all at once. Sure we could get hot loading in here, and do CSS and JS compiling all at once, and a bunch of other things—and we’re going to get to all of that—but for right now our goal is simple: get Webpack compiling JSX, and understand what we’ve done to make it work.

I’ve found it helps to think of Webpack as a three-step process. “Take in some files, do something with them, output a finalized file with the results.” The “do something with them” step brings all kinds of concepts into play, such as loaders, plugins, modules, configuration variables, and … see? This is too much to start with. So let’s start with something simple. Type the following line:

const path = require('path');

We’ve used path before, in app.js, to remove the /public from our static assets when serving them. For example, our images would be served from /images even though they’re stored in /public/images. We’ll be using the same functionality a little further down in this file.

Add a blank line for some separation and then, on line 3, add this code:

module.exports = {
};

The entirety of our webpack config will be stored here, for now. We may in the future build some helper functions which would live below this and be called within the config, but we’ll worry about that if and when we come to it.

Now, remember: Webpack is input, do something, output. So let’s start with input. For now, the only input we care about is the JSX files we’ll be writing for our React app. So, inside the object, add the following lines:

  entry: {
    'javascripts/build.js': './src/index.jsx',
  },

Webpack takes its input in the form of entry points. It does this because it works recursively, which means it will follow the chain of imports all the way down the line, like an FBI agent kicking in the door and then going room-by-room, looking for a serial killer. On the left side we’re defining our output filename, and on the right, our input file. I’ll explain in a second why we have to do it this way.

Since our React app will be entirely built from a starting file, we only need one point of entry. Basically we’re only searching a single house, not a whole block full of them. Our entry is going to be a file that doesn’t exist yet, called index.jsx, located in a top-level directory called src, which will contain all of our React source.

With our input all set, let’s define our output. Add these lines right below the ones you just added:

  output: {
    filename: '[name]',
    path: path.join(__dirname, 'public'),
  },

See that name in brackets? That’s a variable that Webpack will automatically recognize, and it maps to the filenames we defined in the entry block above. So for now, since we only have one entry point, Webpack will see that as filename: 'javascripts/build.js'. What these lines are saying is “Our output file should live at /public/javascripts/build.js.”

We have to use the [name] variable to reference the entry point, instead of just providing the filename here, because we’re going to have multiple entry points and output files in the future when we start also compiling CSS.

All right, now we need to tell Webpack what file extensions to bother paying attention to. Below the output block, add this block:

  resolve: {
    extensions: ['.js', '.jsx'],
  },

That one’s pretty easy … we don’t want webpack wasting its time looking through files that aren’t JavaScript or JSX. With that done, all that’s left is to tell Webpack to use Babel to transpile the source before output. We do that with one more code block, like this:

  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components|public\/)/,
        loader: 'babel-loader',
      },
    ],
  },

This sets a rule that says “look for .jsx files, ignore a couple of directories you might run into, and otherwise when you find a JSX file, run Babel on it.”

That’s it for this file. It should look like this:

const path = require('path');

module.exports = {
  entry: {
    'javascripts/build.js': './src/index.jsx',
  } ,
  output: {
    filename: '[name]',
    path: path.join(__dirname, 'public'),
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components|public\/)/,
        loader: 'babel-loader',
      },
    ],
  },
};

There are two more small tweaks we need to make before we’re ready to start writing JSX. We’re running a little long, here, though, so I’m going to save them for the next tutorial. See you then!

« Previous Tutorial Next Tutorial »