When thinking about a minimum viable Angular 2 application, the configuration files are as close to the metal of the runtime environment as you'll get. In this case, there are two configuration files that will control how npm
and its installed packages will manage the files and the start-up processes: package.json
and tsconfig.json
.
Some part of this recipe may be a review for developers that are more experienced with npm
and its faculties. However, it's important to understand how a very simple Angular 2 project configuration can be structured, so that you are able to wholly understand more complex configurations that are build upon its fundamentals.
The code, links, and a live example of this are available at .
You'll need Node.js installed for this recipe to work; you'll also need an empty project directory. You should create these two skeleton configuration files in the root project directory:
[package.json] { "name": "angular2-minimum-viable-application" } [tsconfig.json] { "compilerOptions": { } }
For a quick and easy way to ensure you have npm
set up and ready to go, use the following:
npm --version
It should spit out a version number if everything is set up properly.
You'll start with package.json
. The package.json
file for a minimum viable application contains three sections:
dependencies
: This is a list of package targets that the production application directly depends upondevDependencies
: This is a list of package targets that the local environment needs for various reasons, such as compilation, running tests, or lintingscripts
: These are custom-defined command-line utilities run through npm
First, you need to add in all the dependencies that your application will need. This includes Angular 2 core modules, which live inside the node_modules/@angular
directory, as well as a handful of library dependencies:
core-js
is the polyfill for the ES6 syntax that the TypeScript compiler depends upon, such as Set
, Promise
, and Map
.reflect-metadata
is the polyfill for the Reflect Metadata API. This allows your TypeScript to use decorators that are not part of the standard TypeScript specification, such as @Component
.rxjs
is available for the ReactiveX JavaScript observables library. Angular 2 natively uses Observables, and this is a direct dependency of the framework.SystemJS
is the dynamic module loader that this project needs for two purposes: to import and map all the source files, and to be able to resolve the ES6 import/export
declarations.zonejs
is the ZoneJS library that provides Angular 2 with the ability to use asynchronous execution contexts. This is a direct dependency of the framework.This leaves you with the following:
[package.json] { "name": "angular2-minimum-viable-application", "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", "systemjs": "0.19.27", "zone.js": "^0.6.23" } }
Next, you need to specify the devDependencies
.
Here's an npm
refresher: devDependencies
are dependencies that are specific to a development environment. Build scripts can use this to differentiate between packages that need to be included in a production bundle and ones that don't.
lite-server
is the simple file server you'll use to test this application locally. This could be replaced by any number of simple file servers.typescript
is the TypeScript compiler.concurrently
is a simple command-line utility for running simultaneous commands from an npm
script.This leaves you with the following:
[package.json] { "name": "angular2-minimum-viable-application", "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", "systemjs": "0.19.27", "zone.js": "^0.6.23" }, "devDependencies": { "concurrently": "^2.2.0", "lite-server": "^2.2.2", "typescript": "^2.0.2" } }
Finally, you need to create the scripts that you'll use to generate compiled files and run the development server:
[package.json] { "name": "angular2-minimum-viable-application", "scripts": { "lite": "lite-server", "postinstall": "npm install -S @types/node @types/core-js", "start": "tsc && concurrently 'npm run tsc:w' 'npm run lite'", "tsc": "tsc", "tsc:w": "tsc -w" }, "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", "systemjs": "0.19.27", "zone.js": "^0.6.23" }, "devDependencies": { "concurrently": "^2.2.0", "lite-server": "^2.2.2", "typescript": "^2.0.2" } }
Each of these scripts serves a purpose, but most you will not need to invoke manually. Here is a brief description of each of these scripts:
lite
starts off an instance of lite-server
.postinstall
is the hook definition that will run after npm install
is completed. In this case, after npm
has installed all the project dependencies, you want to install the declaration files for modules that do not have them. npm
recognizes the pre- and post- prefixes for script strings. Anytime a script is run, npm
will check for scripts with pre- and post- prefixing them and run them before and after the script, respectively. In this recipe, prelite
would run before lite
, and postlite
would run after lite
is run.start
is the definition of the default value of npm start
. This script runs the TypeScript compiler once to completion, then simultaneously invokes the TypeScript compiler watcher and starts up a development server. It is a reserved script keyword in npm
, thus there is no need for npm run start
, although that does work.tsc
kicks off the TypeScript compiler. The TypeScript compiler reads its settings from the tsconfig.json
that exists in the same directory.tsc:w
sets a file watcher to recompile upon file changes.