It is advantageous for many reasons to make it as easy and quick as possible for the client to load and run the code sent from your server. One of the easiest and most effective ways of doing this is by bundling lots of code into a single file. In nearly all cases, it is highly efficient for the browser to load a single file that contains all the dependencies required to bootstrap an application.
Webpack offers many useful tools and among them is the terrific JS bundler. This recipe demonstrates how you will be able to combine your entire application (including npm
package dependencies) into a single JavaScript file that the browser will be served.
The code, links, and a live example of this are available at .
You should have completed all the steps given in the Composing configuration files for a minimum viable Angular 2 application and Composing application files for a minimum viable Angular 2 application recipes. npm start
should start up the development server, and it should be visible at localhost:3000
.
Begin by removing the application's dependency on SystemJS
. webpack
is able to resolve dependencies and bundle all your files into a single JS file. Begin by installing webpack
with the global flag:
npm install webpack -g
webpack
looks for a webpack.config.js
file for instructions on how to behave. Create this now:
[webpack.config.js] module.exports = { entry: "./app/main.js", output: { path: "./dist", filename: "bundle.js" } };
Nothing exceptionally complicated is going on here. This tells webpack
to select main.js
as the top-level application file, resolve all its dependencies to the files that define them, and bundle them into a single bundle.js
inside a dist/
directory.
At this point, you can check that this is working by invoking webpack
from the command line, which will run the bundler. You should see bundle.js
appear inside dist/
with all the module dependencies inside it.
This is a good start, but this generated file still isn't being used anywhere. Next, you'll modify index.html
to use the file:
[index.html] <html> <head> <title>Angular 2 Minimum Viable Application</title> <script src="node_modules/zone.js/dist/zone.js"> </script> <script src="node_modules/reflect-metadata/Reflect.js"> </script> <script src="dist/bundle.js"> </script> </head> <body> <app-root></app-root> </body> </html>
Probably not what you were expecting at all! Since bundle.js
is the application entry point and SystemJS
is no longer needed to resolve any modules (because webpack
is already doing this for you when bundling the files), you can remove the application's dependency on SystemJS.
Since this is the case, you can remove the System dependency from your package.json
and add the webpack
scripts and dependency:
[package.json] { "name": "mva-bundling", "scripts": { "start": "tsc && webpack && concurrently 'npm run tsc:w' 'npm run wp:w' 'npm run lite'", "lite": "lite-server", "postinstall": "npm install -S @types/node @types/core-js", "tsc": "tsc", "tsc:w": "tsc -w", "wp": "webpack", "wp:w": "webpack --watch" }, "dependencies": { "@angular/common": "2.0.0", "@angular/compiler": "2.0.0", "@angular/core": "2.0.0", "@angular/platform-browser": "2.0.0", "@angular/platform-browser-dynamic": "2.0.0", "core-js": "^2.4.1", "reflect-metadata": "^0.1.3", "rxjs": "5.0.0-beta.12", "zone.js": "^0.6.23" }, "devDependencies": { "concurrently": "^2.2.0", "lite-server": "^2.2.2", "typescript": "^2.0.2", "webpack": "^1.13.2" } }
Whether or not webpack
and typescript
belong to devDependencies
here is a matter of dispute and is largely subject to how you manage your local environment. If you've already installed them with the global flag, then you don't need to list it here as a dependency. This is because npm
will search for globally installed packages and find them for you to run npm
scripts. Furthermore, listing it here will install a duplicate webpack
local to this project, which is obviously redundant.
For the purpose of this recipe, it is helpful to have it here. This is because you can ensure that a single npm install
on the command line will fetch all the packages you need off the bat, and this will let you specify the version you want within the project.
Now, when you execute npm start
, the following occurs:
.ts
files into .js
files.bundle.js
in the dist/
directory.lite-server
is started, the TypeScript compiler watcher is started, and the Webpack watcher is started. Upon a .ts
file change, TypeScript will compile it into a .js
file, and Webpack will pick up that file change and rebundle it into bundle.js
. The lite-server
will see that bundle.js
is changed and reload the page, so you can see the changes being updated automatically.Without specifying the configurations more closely, the TypeScript, Webpack, and the lite-server
file watch lists will use their default settings, which may be too broad and therefore would watch files they do not care about. Ideally, TypeScript would only watch .ts
files (which does this with your tsconfig.json
), Webpack would only watch .html
, .js
, and .css
files, and lite-server
would only watch the files it actually serves to the client.