Site icon Treehouse Blog

Bundling Angular with webpack

I love building Angular applications. Because Angular is so modular you can separate your JavaScript code like your controllers and services into multiple files. But adding all of the script references to my HTML file is painful. If only there were some way to use a module loader similar to how modules work in Node…

webpack To The Rescue

webpack is a module loader that works similar to how Node handles modules.

With webpack you can install Angular using NPM, the Node Package Manager.

NPM ships with Node and has become the _defacto_ package manager for front-end JavaScript libraries and frameworks.

In this tutorial, you’ll update an existing Angular application to use CommonJS modules and bundle it using webpack.

I won’t go into why you should use webpack, you can read the motivation behind the project and come to your own conclusions.

Here’s how the starter project is structured:


project/
--app/
----controllers/
------dashboard.controller.js
----directives/
------yep-nope.directive.js
----services/
------github-st
atus.service.js
----app.js
--js/
----angular.min.js
--index.html

Your Angular application is pretty small right now, but you’ll need to update it to use a module loader like webpack so it’s ready for the future. webpack has a wide variety of use cases and configuration options. You’ll be using a very small subset of webpack’s capabilities in this tutorial.

Be Prepared

Before you start you must have Node installed on your machine. You can download Node from nodejs.org. Once Node is installed you’ll be able to follow this tutorial.

You’ll also need to download the starter project for this tutorial.

Review Application

Go ahead and unzip the application and open index.html in your favorite browser. You should see something like this.

See the Pen Angular webpack Starter by Ken Howard (@kenhowardpdx) on CodePen.

Let’s get started migrating this Angular application for use with webpack.

Step One

Update index.html Open the project in your favorite editor. We’ll be bundling our application into two primary files (app.bundle.js and vendor.bundle.js). Bundling is the process of joining multiple files into a single file. In our case, we’ll be bundling all of our application’s code into app.bundle.js. Third party libraries like Angular and other dependencies will be bundled into vendor.bundle.js. This keeps the vendor code separate from our code and makes debugging our application less of a hassle. Take a look at the index.html file. !doctype html Dashboard

Is GitHub Up?

You’ll notice there are more than a few JavaScript files referenced. You’ll need to replace these references with the bundled files you’re about to create. The order you reference these scripts _is_ important because the browser executes them as they are loaded. And because our application depends on Angular, the vendor.bundle.js script needs to load first. <script src=”js/vendor.bundle.js”></script><script src=”js/app.bundle.js”></script>

Great. Your index file is ready. Next you’ll need to configure webpack to create the bundles.

Step Two: Install Dependencies

The downloaded project included _angular.min.js_ in the _js_ directory. In this step you’ll install Angular using NPM so the included Angular library is no longer needed. Delete _angular.min.js_ from the _js_ directory before you continue.

Open a terminal and navigate to the root of your application.

» cd ~/path-to-the-files

Before you install webpack or any of your third party libraries like Angular you’ll need to initialize your project with NPM.

You can do this by simply executing this command in your terminal window:

» npm init -y

The -y flag bypasses the configuration wizard and accepts all of the default configuration options. Omit the -y flag if you’d prefer to use the configuration wizard instead.

Now install your dependencies. At this point, our application only needs Angular and webpack.

» npm install angular webpack --save-dev

If you are familiar with NPM you’ve probably noticed that we’re using the --save-dev flag here instead of the --save flag. It is up to you and your build process on how you install dependencies. I recommend only using --save when a server-side application requires third-party modules at run-time. Otherwise use the --save-dev flag. In the case of this tutorial, Angular and webpack are part of a build process so you should use the --save-dev flag.

Great. You’ve got Angular and webpack installed!

Step Three: Configuring webpack

webpack needs to know where your application files live and where you want to store the bundles. To do this it looks for the webpack.config.js file in the root of your project. This file informs webpack on how you want your application bundles separated and if you have any pre-processing tasks to perform.

Create webpack.config.js in the root of your project.

var webpack = require('webpack');
module.exports = {
context: __dirname + '/app',
entry: {
app: './app.js',
vendor: ['angular']
},
output: {
path: __dirname + '/js',
filename: 'app.bundle.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js")
]
};

This file needs to export a configuration definition that webpack can interprit. The key properties here are context, entry, and output.

context: This is an absolute path to your application’s source files.
entry: The main file that bootstraps your Angular application. In our case we passed an object with keys of app and vendor. This generates multiple bundle files.
output: An object that configures where the bundle files are saved once generated.

There’s also a plugins property. The only plugin we need is built into webpack. It allows you to split your application’s code and your third party code into separate files. You can read more about code splitting here].

Good work so far. You’ve got webpack installed and configured. Next you’ll edit your Angular application to use CommonJS modules.

Step Four: Require Modules

If webpack were to bundle your code at this point it would only bundle the app.js file that is referenced in your webpack.config.js files. This is because your app.js file hasn’t required any additional files.

To include _yep-nope.controller.js_, _github-status.service.js_, and _dashboard.controller.js_ you’ll need to require them within your app.js file.

You could simply require these files at the bottom of app.js.

// app.js
...
require('./directives/yep-nope.controller');
require('./services/github-status.service');
require('./controllers/dashboard.controller');

This works well for small applications, but it could get out of hand with larger applications.

Instead of simply requiring these files create a new file called index.js in the controllers folder. This file will act as the entry point for all of your application’s controllers.

This file should require Angular and your _dashboard.controller.js_ file/.

'use strict';

var angular = require('angular');

angular.module('dashboard').controller('dashboardController', require('./dashboard.controller'));

Be sure to remove the controller definition line from _dashboard.controller.js_.

Now do the same for the directives directory.

Create the index.js which will act as the entry point for all your application’s directives.

This file should require Angular and your _yep-nope.directive.js_ file.

'use strict';

var angular = require('angular');

angular.module('dashboard').directive('yepNope', require('./yep-nope.directive'));

Remove the directive definition line from _yep-nope.directive.js_.

Next create an index.js file in the services folder. This file will act as the entry point for all of your services.

This file should require Angular and your _github-status.service_ file.

'use strict';

var angular = require(‘angular’);

angular.module(‘dashboard’).service(‘GithubStatusService’, require(‘./github-status.service’));

Now in _github-status.service.js_ remove the service definition at the bottom of the file and add a module.exports definition and export the _GithubStatusService_ function.

The last line of the file should look like this

module.exports = GithubStatusService;

The final piece of the puzzle is to require these new files in your app.js file

// app.js
...
require('./directives');
require('./services');
require('./controllers');

When your application grows and you need to add new directives, services, and controllers you’ll need to create the Angular definitions in _directives/index.js_, _services/index.js_, or _controllers/index.js_ before they’ll be included in your bundle.

Your Angular application is ready to go. Next you’ll configure NPM to bundle your code using webpack.

Step Five: Configuring Tasks

When you initialized the project with the npm init command at the beginning of this tutorial you might have noticed a file named package.json was in your project’s root directory. The package.json is responsible for keeping track of your project’s dependencies. It also provides a way of running various tasks via the scripts option. When you create a script Node can execute your project’s dependencies. We’re going to add a bundle task to bundle our code.

Open package.json in your text editor.

Add a new line below the test script. Call the task “bundle” and have it execute “webpack”. The scripts block should look something like this:


"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"bundle": "webpack"
},

In your terminal execute npm run bundle<c/ode>. The terminal should output something like this


» npm run bundle

angular-webpack@1.0.0 bundle /Users/ken/Projects/angular-webpack
webpack

Hash: fa17ee9ecec0b19a73ae
Version: webpack 1.12.12
Time: 550ms
Asset Size Chunks Chunk Names
app.bundle.js 1.42 kB 0 [emitted] app
vendor.bundle.js 1.12 MB 1 [emitted] vendor
[0] ./app.js 82 bytes {0} [built]
[0] multi vendor 28 bytes {1} [built]
[1] ./services/index.js 145 bytes {0} [built]
[4] ./services/github-status.service.js 373 bytes {0} [built]
[5] ./controllers/index.js 147 bytes {0} [built]
[6] ./controllers/dashboard.controller.js 278 bytes {0} [built]
+ 2 hidden modules

Now run the application in the browser.

» open index.html

You did it! Your Angular application is up and running using webpack.

ES6 Modules

In this tutorial you’ve learned how to migrate a simple Angular application for use with webpack using the standard exports/require CommonJS module pattern. While this works in practice today, more and more application developers are making the leap to ES6 module loading and transpiling their code using tools like Babel and TypeScript.

If you are interested in developing your application using ES6 modules you should take a look at the babel-loader and ts-loader plugins for use with webpack.

Get Coding

You’re ready to start building your own applications using Angular and webpack. If you have questions or hit any stumbling blocks be sure to leave a comment below. We’re all in this together!

You can download the final project files of this tutorial to compare them with your copy.


 

Want to learn more from Ken? Check out his newest course on Treehouse, Building a MEAN Application.

Exit mobile version