Webpack for ngUpgrade, Part 3: The Development Server

Upgrading AngularJS
9 min readFeb 25, 2018

--

Mastering Webpack during a real world ngUpgrade requires four things:

  1. An understanding of the basics (the first guide)
  2. Setting up TypeScript (the previous guide)
  3. A development environment (this guide)
  4. Environment-specific builds, especially production (the final guide)

In the last guide, I gave you a little taste of what Webpack can do with TypeScript and ES6 modules. Since our end goal is to convert all of our components and services to TypeScript and remove them from index.html in order to add them to our bundle, you can imagine it would get really tedious having to manually run Webpack from the command line every single time something changes.

In this next part of our Webpack for ngUpgrade series, we’re going to install webpack-dev-server and set up some npm scripts to just keep it running for us in the background as we make changes.

(If the length of this guide freaks you out, just hop over to our course for step-by-step videos on this topic and even advanced Webpack tactics.)

Our Starting Point

Take a minute and clone our course sample project on GitHub (don’t forget to run npm install). I’ll reference different commits throughout this guide so you can see examples of everything we cover here. Checkout this commit to see our starting point:

git checkout a31619cc19b75c3b16f9b867e1ccf45b3df3ecf1

You’ll see where we left off last time:

  • We’re using ts-loader to bundle TypeScript with Webpack
  • We’re resolving .ts extensions
  • We’ve renamed our root to app.ts and changed our Webpack entry point

Now it’s time to set up our dev server. Let’s jump into the code.

Webpack Dev Server

As you might guess, the first step is just to install Webpack Dev Server. It’s a node module and we can just install it with:

npm install --save-dev webpack-dev-server 

The next thing we need to do is add a devServer property to our Webpack config. It’s going to look like this:

devServer: {                               
contentBase: "./",
port: 9000
}

Webpack dev server has some default options set, but I find for real development on real applications, I need to tweak it a bit. We only really need two options right now. The first is contentBase. This just tells the server where to serve our content, and we’re going to keep this real simple right now and just serve it from this directory. Later on, we’re going to change this, because our goal is to eventually move the dist folder out and move our index.html file out as well. We want to keep our development files separate from what we’re actually deploying to the server. Right now, we’re in this flux state where we’re doing both at once. We’ll be able to change this content base option later.

The next thing we’re going to do is set our port to 9000. It doesn’t really matter for this demo, but in the real world, chances are you’ll be working with multiple apps at your company that each need their own port so they don’t conflict.

That’s all we need to do, so let’s try running it and see what it looks like. Open the terminal up and type webpack-dev-server. It starts and you can see that it’s running at local host with port 9000, and you can see in the output that Webpack is bundling our application. You can also see that it’s serving from our directory:

Our dev server output.

If you control-click on that link, you’ll see that our application is running in the browser. That in and of itself is not that impressive, but let’s go change the title and see what happens. Open up home.ts and change the title on line 11. Add some exclamation points and save it — and immediately, we can see in the terminal that Webpack re-bundled and our browser refreshed. That is pretty cool! If you’re coming from Gulp or Grunt, you’ll already be familiar with this kind of watch process, but you’ll also notice that Webpack is way faster with these kinds of live changes.

This is great, but would be nice if we had a little bit more flexibility with how we run this command. We can do that with npm scripts.

Adding npm Scripts

It’d be nice if we didn’t have to always type the Webpack command directly in the terminal, especially if we need to pass in other options or we need to combine it with other commands later on. We don’t have a huge need for this yet, but as our build process grows more complex and as we convert more and more pieces of our application over to TypeScript, we’ll want to be able to just run an npm script that will kick off the Webpack server and let’s us get to work.

We’ll also want to differentiate between a production command that just runs Webpack to bundle everything and our Webpack development server that we use for development. We can do this pretty easily in the script section of our package.json file.

The Production Build

Let’s add our production build script first to run Webpack:

"scripts": {                           
"build": "webpack --bail --progress",
"test": "echo \"Error: no test specified\" && exit 1" }

I’m going to pass in a couple of options that I like. There’s the bail flag that just aborts the compilation process on the first error. Then there’s the progress flag that just prints the compilation progress as a percentage in the terminal.

Scripts have access to the binaries within your node modules folder. This is why earlier I had us install Webpack and Webpack Dev Server locally instead of globally. That way, anyone who works on this application can run these scripts and have access to those binaries, regardless of what’s globally installed on their system.

So let’s take a look a look at this script in action. In the terminal, just run:

npm run build

(You could also use yarn build.)

Our super simple prod build output.

You can see that it ran Webpack with the bail and progress flags.

Obviously there’s not much going on right now for this to make a huge difference, but it does in fact bundle our file. We’ll be building up on this production script in our next guide.

The Dev Server Build

Now, let’s add our dev script to run the dev server:

"scripts": {                           
"build": "webpack --bail --progress",
"dev": "webpack-dev-server",
"test": "echo \"Error: no test specified\" && exit 1" }

Now I can just run npm run dev (or yarn dev) and see the same output we did before — the dev server is running and Webpack has bundled our application. Neat!

You might not see the power in these two scripts quite yet, and that’s okay, but we’ll be able to build on these later as we enhance our build for production and other environments. We’ll be able to pass in additional arguments or an environment configuration and get really sophisticated now that we’ve laid our foundation.

There’s one last development tool I want to get set up for us before we move forward in converting all the rest of our application to TypeScript: source maps.

Sourcemaps in Webpack

We’re nearly done with our development setup, which is going to lead us into converting the rest of our application to TypeScript and ES6 modules and then eventually setting up a nice production build. All of this will get us ready for ngUpgrade and moving to Angular.

Right now, our bundle contains:

  • AngularJS
  • The AngularJS router
  • Our app module root (app.ts)
  • The home component (home.ts)

If you look at the bundle in the dist folder, you can see that, even with only these few things, it’s already 1.3mb. Now, don’t get too worried. We haven’t covered anything about optimization (like uglification). The important part for is that if we look at our bundle file, we can see it’s quite large — over 35k lines. This is partially because we haven’t extracted our vendor files (we cover optimization and extracting vendor files in the course).

However, it would be really nice to have some source maps so we could just get to our TypeScript source for debugging without having to weed through this giant file and all this bootstrapping code. Webpack provides many source map options (probably more than you thought there could be). If you look over in the documentation for Webpack, you can see some thorough explanations of different source map options for both development and production. We’re not going to stress out too much about this right now because all we’re trying to do is speed up our development process. We’re going to make it really easy on us and just use the source-map option.

Now, the source-map option is a little slow. It generates separate files instead of in-line files. That’s okay. We’re going to come back to this subject later on once we’ve broken out our config into a development config and a production config. We’re not there yet. Let’s add this new option in to our config.

Back in webpack.config.js, add the following above the dev server option:

devtool: 'source-map',

If you run our build script with npm run build, you can see that it runs everything, and it pops out a .map file. Now, in production, that’s really not ideal. We don’t want source maps generated for production, and in development, we’d rather have inline source map. We can do all that, but right now, we still have some vendor files mixed in, and inline source maps will just generate a file that’s too large to manage. We’ll come back to that later on, but we can run our development server again with npm run dev and hop back over to the browser to see what the source maps look like.

In the browser, if you open up Chrome’s dev tools, you’ll notice there’s a new item in the sources tree with the Webpack server:

Source maps!

We can now see source maps for everything that’s in our bundle. In fact, I could search for our home component in our bundle file, set a breakpoint, and it will jump right over to that source map. That way, when we’re debugging, we’ll jump straight to the code instead of having to parse through thousands of lines in the bundle.

Where to Go Next

Over the last three guides, I’ve shown you how to set up your very first super simple Webpack build. Now, this simple build is great for when we’re just developing and running in Chrome and working in the browser. But if we want to take advantage of all the new innovations of ES6 or TypeScript (which we do) or if we need to optimize this application for a real production environment (which we must do to keep our jobs), we’re going to need to go further with Webpack by introducing loaders, plugins, and different configurations for different environments. We’ll cover some of this in the next guide, and all of it is available in the course.

It’s now time to finish converting the rest of the sample application to TypeScript and ES6 modules, just like we did with the home component. Once that’s done, you’ll be ready for the next guide, where we’ll enhance our Webpack build by breaking it out for different environments. This where you’ll really start to see the power of Webpack!

Love this guide?

If you love this guide, I’ve got 200+ detailed videos, quiz questions, and more for you in my comprehensive course UpgradingAngularJS.com. I created it for everyday, normal developers and it’s the best ngUpgrade resource on the planet. Head on over and sign up for our email list to get yourself a free Upgrade Roadmap Checklist so you don’t lose track of your upgrade prep. And, while you’re there, check out our full demo.

--

--

Upgrading AngularJS

The best ngUpgrade resource on the planet. Comprehensive, step by step course to help you move from AngularJS to Angular.