Hello and welcome back! I’m so glad to see that you’ve accepted my invitation to come on this epic Code Quest to the end of grok (of React) and back! If you have no idea what I’m talking about you might like to take a moment to breeze through my last post on creating your first React component. Equally if you’d like to follow along with the code examples in this tutorial you might like to quickly clone the part 1 branch of the accompanying github repository.

If, however, you are a seasoned code-venturer and an official acolyte of The Reactionary guild after having accepted my invite in the last tutorial then you’ll be pleased to know that the guild has double in size since my last post. That’s right our membership is now up to two! Hard to believe I know but we mustn’t rest on our laurels if we are to maintain our weekly 100% growth. We need to be able to make our invitation application quicker to develop and easier to deploy.

To this end, in this post we will be exploring the vast expanse that is javascript task runners and bundlers! Now is not a time to fret so avoid doing so. I will be walking you through how to make a very basic build pipeline for our app that we built last week. Once again I wouldn’t expect to find what we build to be the finished product in any production system but it will certain give us a solid foundation on which we can build our knowledge. Let’s not waste anymore time, let’s jump in!

In the interests of brevity I’m going to assume that you have a basic knowledge of Node.js and NPM. If you don’t and you are considering learning React then it might be worth your time at least getting the basics down because you will interact with these tools quite a bit. At very least you’ll use it in the capacity of interacting with your build pipeline. For now all you will need is to grab the installer for Node off their website and install it.

You should now have both Node and NPM installed on your machine. Any more instruction than that for now is probably surplus to requirements but if you do find you’re having trouble then google is your friend on this one.

Once you have Node installed we will first initialize our project as a npm package. Obviously we wont be releasing our application to the public any time soon but initialising our application as a node module does provide us with a package.json which will be a good for you to be able to refer back to.

To initialize our project as an npm package you just need to open up a command prompt and navigate to the root of your project folder. I have been building CodeQuest locally at C:\Project\CodeQuest so I will go into that directory in the command prompt. From there you should run the command:

This will ask you for a whole heap of variables, which for the purposes of this tutorial aren’t important so, go ahead and accept the defaults for all of them. Once you’re done you will find that you have a package.json in your root folder. The exact detail of this file is outside of the scope of this tutorial but it’s enough to say that this defines the configuration of your code base in terms of it being a node module. The part we’re particularly interested in here is the fact that this file can track our dependencies on other npm packages. Let’s add a few now.

First let’s add the react and react-dom npm packages as dependencies for our build pipeline. If we are going to have a build pipeline we might as well use it to take care of supplying and keeping track of our vendor scripts after all! To bring in these packages in as dependencies you can run the command:

Once again you should run these commands when your command prompt is at the root of your project. When you execute these commands you will see some loading bars come up, once these are done you should have a node_modules folder in your root which, along with a number of others, will be a react folder and react-dom folder. If you’ve gotten this far you’re off to a good start.

Next we need to install our dev dependencies. These are the packages which our build pipeline will rely one to do its work. You can use the following command:

Also whilst you’re at it go ahead and install webpack and webpack-dev-server globally so you have access to them on the command line like this:

“WHOA WHOA WHOA! What is all this you’re throwing at me Zac!” I hear you saying as you blindly copy+paste the command into your command line and you’re right to question me. Too often in a node environment you end up unduly bloating yourself with all sorts of packages that you ultimately don’t need so let’s take a quick moment to break down each of these packages and a brief description of what it does:

This is the core code package for Babel.js which is a javascript compiler. We probably don’t explicitly need this right now but it’s worth having. Remember in the last tutorial when I said that the code we wrote wasn’t exactly “production ready”? Well in real life™ we actually use ES6 javascript or Typescript to write our components and we also use a proprietary “markup-like” language called JSX. All of these topics I hope to cover in near future posts but basically having this installed is just future proofing our tutorial series.

This package is a preset for use with babel which gives babel specific instructions on how it should compile the special syntax that we use in react to plain old javascript for use in the browser.

As of writing this post Webpack is a relative newcomer to the bundling scene, but boy has it made an impact. In a nutshell webpack takes all your different types of files for your application and bundles them all in neat little packages ready to released into the world. For less of a wishy washy explanation of the technology feel free to jump over to the webpack website and take a look.

Babel-loader, css-loader, style-loader, file-loader and image-webpack-loader
Each of these packages are loaders that you can provide to webpack which gives webpack instructions on how to deal with certain files when it comes to loading them into it’s framework and anything specific it needs to do with them when it’s bundling them together. You can configure webpack to use different loaders different files. We’ll see how to do this in a moment.

As if those guys and gals at webpack hadn’t already been useful as heck enough, they had to go and make a package that you can pull into your pipeline which gives you a nice little hosting service for your application within node. Now they say themselves that this far from adequate for a running a production server but itself certainly good enough for development and comes with heaps of funky features we can use to make our development process silky smooth. We’ll explore these features in another post.

Ok so now we have our development pipeline packages all setup let’s start pointing it at our application! The first thing we should do is create for ourselves a webpack.config.js file in the root of our directory. This file is going to do pretty much what it says on the tin. When webpack runs it’s going to look, by default, in the root of the application for it’s configuration. Go ahead and put this code into your new webpack.config.js file:

If we begin with the first property of the configuration; the context is the absolute path for which relative calls in webpack are resolved in relation to. Here we have set it to the absolute path of of our project’s root directory by combining the node variable __dirname and the path /src. This means that if webpack were trying to resolve the path ./test in the course of it’s bundling duties then that path would be resolved to, in my case, C:\Projects\CodeQuest\test. There is a gotcha here as well, you will notice we used the node module path to give us the absolute path rather than just string concatenating __dirname and the string “/src” this is gives us a better cross platform approach because webpack hates back slashes in paths and this is is how windows represents it’s paths. I have to admit that it does seem very odd that webpack would have this limitation but I’ve yet to investigate the in-depth details as to why this is. I’d say either there is some complicating factor that I’m not seeing or it’s just simply they feel they have bigger fish to fry. Either way now you can duck and weave out of this gotcha.

The next property, entry, is the first file that webpack will look in when it begins bundling our application together. From this file we will be using CommonJS syntax to require modules our resulting bundle.

The final property kind of speaks for itself. The output object defines properties that describe where the bundle will be outputted once it has been bundled. We’ve decided to put our bundle in the dist folder in the root of our project and we’ve called our bundle app.js.

So now that we have our basic configuration for webpack all setup we can start setting up our project to fit this configuration. You will have noticed that webpack is going to be looking in a folder called src for our source files so let’s create that in our root directory first.

Next let’s copy all of our current code base into our new src folder. That would be the assets, css and script folders as well as the index.html. Finally you’ll remember that webpack was going to be looking for a file named index.js. Now watch out here, webpack is going to be looking for ~/src/index.js, why? Because webpack has it’s context set to the src folder so the path ./index.js resolves to ~/src/index.js. Let’s create an index.js file in the src folder and put the following code in it:

So, here, you can see the CommonJS require syntax at work. The first line is requiring in our javascript file. All pretty normal so far. The next two requires might seem a bit weird though, bring in a css and html file into a javascript bundle!! Well not necessarily what we are actually doing here is telling webpack what we want in our bundle and our bundle may consist of a number of different types of file. Webpack will take all of these, run them through the loader, middleware and plugins that it has available and then spit out static files of each kind all ready for use. You’ll see this in action soon.

With the power of webpack there is one further thing we can free ourselves of; the React and ReactDOM globals variables that we had created for ourselves by including the script tags on the index.html. Do you remember that we installed npm packages for each of these? Well now we can use webpack to require these packages into our codeQuest script as local variables and through webpack’s compilation the variables create will remain local to that script. Open up your script/codeQuest.js file and add these two require’s to the top of the file:

So now that we know that webpack will do all this nice neat bundling for use we can afford to simplify our index.html down quite a bit. We no longer need to concern ourselves with bringing in the css and with us requiring in the React npm packages we no longer need to bring in our CDN versions of the react javascript files. Finally we will need to modify the src of our script tag for our application because webpack will now be outputting the file with name app.js rather than the path we have at the moment. By then end of all that the index.html will look like this:

We’re almost ready to kick off our webpack builds now. All that’s left to do is hook up those loader that I was talking about earlier, those ones that help webpack to know what to do with the html and css files that we’ve given it. To do this add the highlighted code below to your webpack.config.js file:

The first loader here is for babel. This configuration says, for each file you find to bundle, test it to see if the file name ends in .js. If it does and it’s not in the node_modules folder (we don’t want to bundle our dependencies up and by accident!) then hand the file to babel for compilation using the react preset.

The next loader does a similar thing except it looks for css and sends it to the style and css loaders respectively. Now the css loader is what actually allows you to require a css file in the first place and the style loader will take that css that you’ve loaded and place a <style> tag in the DOM for you so that your bundles will start using it.

Now because the css loader is so clever it can tell that we have a background image (for our scroll) included in the css and it will go looking for that file and bundle that up as well. Because of that we are also going to have to define a file loader that can load this image into webpack ready to bundle.

The last loader is a simple file loader to take our index.html and include that in our bundle as well.

So webpack is ready to go now and if you were to run webpack directly from the command line then you would find that the bundle gets created in the dist folder. You could open up that static index.html in your favourite web browser and you’d see the friendly screen you were greeted with at the end of the last tutorial. But I did mention that I’d be helping you to learn how to make a build pipeline and whilst we don’t have a lot of tasks to run at this point we can at least start looking at how we would automate our tasks for when we have a lot more.

Go ahead and open up for package.json file in the root directory of your project and in the scripts key of that json add the following properties:

This will defined for you two tasks; start which you can use to open up your solution hosted in a webpack-dev-server instance and build which will simply bundle our solution into the dist folder for us to do what we want with.

There is one final thing we need to do before we can use these tasks though and that is provide configuration for the webpack-dev-server and we can do this by adding the following to the webpack.config.js:

With that you are all ready to go and start using your shiny new Webpack and NPM build pipeline. You can kick off a build by running this command in a command prompt:

And to start the dev server you can run:

As I mentioned earlier this is far from something you’d see on production but it’s a great start and it’s certainly a step closer to the real world than our static files that we start with. Try not have too much fun with your new pipeline and I’ll see you on your next adventure.