Starting an Angular 2 RC.5 project

This blog is updated on August 9, 2016

The current version of Angular is Release Candidate 5. It has been released an hour ago, and I’ve started learning again. The major breaking change is how the app is loaded. The RC.5 introduced the concept of modules and now the app is not loaded by invoking the bootstrap() method. You have wrap the root component of your app into a module, which is a class decorated with the @NgModule() annotation and declare your component (or several components, services, directives, providers, and pipes) inside this annotation.

If the Angular code is dynamically compiled in the browser (not to be confused with transpiling), this is called just-in-time compilation (JIT). If the code is precompiled, it’s called ahead-of-time (AoT) compilation. In this blog we’ll do the JIT compilation.

To start a new project managed by npm, create a new directory (e.g. angular-seed) and open it in the command window. Then run the command npm init -y, which will create the initial version of the package.json configuration file. Normally npm init asks several questions while creating the file, but the -y flag makes it accept the default values for all options. The following example shows the log of this command running in the empty angular-seed directory.

$ npm init -y

Wrote to /Users/username/angular-seed/package.json:

{
  "name": "angular-seed",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Most of the generated configuration is needed either for publishing the project into the npm registry or while installing the package as a dependency for another project. We’ll use npm only for managing project dependencies and automating development and build processes.

Because we’re not going to publish it into the npm registry, you should remove all of the properties except name, description, and scripts. Also, add a “private”: true property because it’s not created by default. It will prevent the package from being accidentally published to the npm registry. The package.json file should look like this:

{
  "name": "angular-seed",
  "description": "An initial npm-managed project for Chapter 2",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

The scripts configuration allows you to specify commands that you can run in the command window. By default, npm init creates the test command, which can be run like this: npm test. Let’s replace it with the start command that we’ll be using for launching the live-server that’s we’ll add to the generated package.json a bit later. Here’s the configuration of the scripts property:

{
  ...
  "scripts": {
    "start": "live-server"
  }
}

You can run any npm command from the scripts section using the syntax npm run mycommand, e.g. npm run start. You can also use the shorthand npm start command instead of npm run start. The shorthand syntax is available only for predefined npm scripts (see the npm documentation at https://docs.npmjs.com/misc/scripts).

Now we want npm to download Angular to this project as a dependency. We want Angular with its dependencies to be downloaded to our project directory. We also want local versions of SystemJS, live-server, and the TypeScript compiler.

npm packages often consist of bundles optimized for production use that don’t include the source code of the libraries. Let’s add the dependencies and devDependencies sections to the package.json file right after the license line:

    "dependencies": {
 "@angular/common": "2.0.0-rc.5",
    "@angular/compiler": "2.0.0-rc.5",
    "@angular/core": "2.0.0-rc.5",
    "@angular/forms": "0.3.0",
    "@angular/http": "2.0.0-rc.5",
    "@angular/platform-browser": "2.0.0-rc.5",
    "@angular/platform-browser-dynamic": "2.0.0-rc.5",
    "@angular/router": "3.0.0-rc.1",
    "systemjs": "0.19.36",
    "core-js": "^2.4.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "angular2-in-memory-web-api": "0.0.15"
  },
  "devDependencies": {
    "live-server": "1.0.0",
    "typescript": "^2.0.0"
  }

NOTE:This version uses the very latest version of Angular Router, which is currently 3.0.0-rc.1.

Now run the command npm install on the command line from the directory where your package.json is located, and npm will start downloading the preceding packages and their dependencies into the node_modules folder. After this process is complete, you’ll see dozens of subdirectories in node_modules, including @angular, systemjs, live-server, and typescript.

angular-seed
├── index.html
├── package.json
└── app
└── app.ts
├──node_modules
    ├── @angular
    ├── systemjs
    ├── typescript
    ├── live-server
    └── …

In the angular-seed folder, let’s create a slightly modified version of index.html with the following content:

<!DOCTYPE html>
<html>
<head>
  <title>Angular seed project</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <script src="node_modules/core-js/client/shim.min.js"></script>
  <script src="node_modules/zone.js/dist/zone.js"></script>
  <script src="node_modules/reflect-metadata/Reflect.js"></script>

  <script src="node_modules/typescript/lib/typescript.js"></script>
  <script src="node_modules/systemjs/dist/system.src.js"></script>
  <!-- script src="node_modules/rxjs/bundles/Rx.js"></script -->
  <script src="systemjs.config.js"></script>
  <script>
    System.import('app').catch(function(err){ console.error(err); });
  </script>
</head>

<body>
<app>Loading...</app>
</body>
</html>

The script tags load the required dependencies of Angular from the local directory node_modules. The Angular modules will be loaded according to the SystemJS configuration file systemjs.config.js. Note the commented out script tag for Rx.js. I’ll show you two ways of configuring SystemJS, and in the first version this line is not needed.

Configuring SystemJS. Take 1.

The SystemJS configuration file systemjs.config.js can look as follows:

System.config({
    transpiler: 'typescript',
    typescriptOptions: {emitDecoratorMetadata: true},
    map: {
        'app' : 'app',
        'rxjs': 'node_modules/rxjs',
        '@angular'                    : 'node_modules/@angular'
      },
      packages: {
        'app'                              : {main: 'main', 
                                              defaultExtension: 'ts'},
        'rxjs'                             : {main: 'index.js'},
        '@angular/core'                    : {main: 'index.js'},
        '@angular/common'                  : {main: 'index.js'},
        '@angular/compiler'                : {main: 'index.js'},
        '@angular/router'                  : {main: 'index.js'},
        '@angular/platform-browser'        : {main: 'index.js'},
        '@angular/platform-browser-dynamic': {main: 'index.js'}
      }
});

NOTE:This version loads all Angular modules as separate files, which causes the browser to make 300+ network requests. No good. We can do better.

The app code will consist of three files:
– app.component.ts – the one and only component of our app
– app.module.ts – The declaration of the module that will include our component
– main.ts – the bootstrap of the module

Let’s create the file app.component.ts with the following content:

----
import {Component} from '@angular/core';

@Component({
    selector: 'app',
    template: `<h1>Hello {{ name }}!</h1>`
})
export class AppComponent {
    name: string;

    constructor() {
        this.name = 'Angular 2';
    }
}

Now you need to create a module that will contain our AppComponent. This code we’ll place inside the app.module.ts file:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';

@NgModule({
    imports:      [ BrowserModule ],
    declarations: [ AppComponent ],
    bootstrap:    [ AppComponent ]
})
export class AppModule { }

This file just contains the definition of the Angular module. The class is annotated with @NgModule that includes the BrowserModule that every browser must import. Since our module contains only one class, we need to list it in the declarations property, and list it as the bootstrap class.

In the section packages of the SystemJS config file we mapped the name app to main.ts that will look like this:

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule }  from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

The last line of the above script actually compiles and loads the module.

Start the application by executing the npm start command from the angular-seed directory, and it’ll open your browser and show the message “Loading…” for a couple of seconds, followed by “Hello Angular 2!”. If you check the Network panel in Chrome Developer tools, it shows more than 300 network requests and more than 5MB of the downloaded code. Not all of this code is Angular though. SystemJS uses the TypeScript compiler in the browser, and it weighs 3Mb.

Configuring SystemJS. Take 2.

To lower the number of network requests and the download size let’s change the systemjs.config.js to use the minimized and bundled versions of Angular packages:

System.config({
    transpiler: 'typescript',
    typescriptOptions: {emitDecoratorMetadata: true},
    map: {
      '@angular': 'node_modules/@angular'
    },
    paths: {
      'node_modules/@angular/*': 'node_modules/@angular/*/bundles'
    },
    meta: {
      '@angular/*': {'format': 'cjs'}
    },
    packages: {
        'app'                              : {main: 'main', 
                                              defaultExtension: 'ts'},
       '@angular/core'            :{main: 'core.umd.min.js'},
       '@angular/common'          :{main: 'common.umd.min.js'},
       '@angular/compiler'        :{main: 'compiler.umd.min.js'},
       '@angular/platform-browser':{main: 'platform-browser.umd.min.js'},
       '@angular/platform-browser-dynamic': 
                            {main:'platform-browser-dynamic.umd.min.js'}
    }
});

If you use forms and http, add the following two lines to the above file:

        '@angular/forms'                   : {main: 'forms.umd.min.js'},
        '@angular/http'                    : {main: 'http.umd.min.js'},

NOTE: I’ve removed the Rx.js configuration from this version of systemjs.config.js, and you’ll need to uncomment the line that loads Rx.js in the index.html shown earlier.

If you run the same application, it’ll make only 16 network requests and the download size is less than 5MB (it’ll take just a half a second). Much better, isn’t it? In chapter 10 of our Angular 2 Development with TypeScript book we explain how to minimize a small Angular app to only 150Kb with Webpack.

Using the AoT compilation will decrease the application footprint even more because the app sent to the browser won’t include the internal Angular compiler. After learning how to perform the AoT compilation I’ll write a sequel to this blog.

You can find the source code of our angular-seed project (yes, the RC.5 version) at https://github.com/Farata/angular2typescript/tree/master/chapter2/angular-seed.

That’s all there is to it for the Hello World type application.

I’d like to thank Anton Moiseev, my coauthor of the Angular 2 book for his contribution to this blog. We often run online Angular 2 trainings, and if you’re interested in learning Angular 2 in depth, join one of our workshops (see the dates of the upcoming trainings at https://yakovfain.com/ ).

38 thoughts on “Starting an Angular 2 RC.5 project

    1. You might have made a typo. It’s @angular, not angular. Just ran the npm install – works fine.

  1. Hi, Yakov. Thanks for your tuturial. Are you plane to make a tutorial on how to use Angular 2 with back end writing in Java?

  2. Hi Yakov,
    Thank you for the best Tutorial. Do you have any Example of using angular2 with MVC and WebApi with Visual studio 2015 ?

      1. Hello,
        Thank you for sharing the useful link.
        Can you please share details for the application which retrieves Data from the Database (SQL server)?

  3. Hi Yakov, can you help me, please.
    I wrote the follow code:

    this.registerForm = _fb.group({
    passwords:_fb.group({
    password: new Control(this.registerContact.password,
    Validators.compose([Validators.required, Validators.minLength(8)])),
    repeat_password: new Control(this.registerContact.repeat_password,
    Validators.validator:checkRepeatPassword})
    });
    What is the best way to get *password* and *repeat_password* from here ?

    1. let formValue = this.registerForm.value;
      // Value:
      {
      passwords: {
      password: ‘asd123’,
      repeat_password: ‘asd123’
      }
      }

  4. I am getting errors when trying to run npm-install. The error information is as follows:

    C:\zzWork\Omnipot\Main\Source\OmniPot\src\OmniPot>npm install
    npm ERR! Windows_NT 10.0.10586
    npm ERR! argv “C:\\Program Files (x86)\\nodejs\\node.exe” “C:\\Program Files (x86)\\nodejs\\node_modules\\npm\\bin\\npm-cli.js” “install”
    npm ERR! node v5.10.1
    npm ERR! npm v3.8.3

    npm ERR! No compatible version found: angular2@2.0.0-rc.1
    npm ERR! Valid install targets:
    npm ERR! 2.0.0-beta.17, 2.0.0-beta.16, 2.0.0-beta.15, 2.0.0-beta.14, 2.0.0-beta.13, 2.0.0-beta.12, 2.0.0-beta.11, 2.0.0-beta.10, 2.0.0-beta.9, 2.0.0-beta.8, 2.0.0-beta.7, 2.0.0-beta.6, 2.0.0-beta.5, 2.0.0-beta.4, 2.0.0-beta.3, 2.0.0-beta.2, 2.0.0-beta.1, 2.0.0-beta.0, 2.0.0-alpha.55, 2.0.0-alpha.54, 2.0.0-alpha.53, 2.0.0-alpha.52, 2.0.0-alpha.51, 2.0.0-alpha.50, 2.0.0-alpha.49, 2.0.0-alpha.48, 2.0.0-alpha.47, 2.0.0-alpha.46, 2.0.0-alpha.45, 2.0.0-alpha.44, 2.0.0-alpha.42, 2.0.0-alpha.41, 2.0.0-alpha.40, 2.0.0-alpha.39, 2.0.0-alpha.38, 2.0.0-alpha.37, 2.0.0-alpha.36, 2.0.0-alpha.35, 2.0.0-alpha.34, 2.0.0-alpha.33, 2.0.0-alpha.32, 2.0.0-alpha.31, 2.0.0-alpha.30, 2.0.0-alpha.29, 2.0.0-alpha.28, 2.0.0-alpha.27, 2.0.0-alpha.26, 2.0.0-alpha.25, 2.0.0-alpha.24, 2.0.0-alpha.23, 2.0.0-alpha.22, 2.0.0-alpha.21, 2.0.0-alpha.20, 2.0.0-alpha.19, 2.0.0-alpha.18, 2.0.0-alpha.17, 2.0.0-alpha.16, 2.0.0-alpha.15, 2.0.0-alpha.14, 2.0.0-alpha.13, 2.0.0-alpha.12, 2.0.0-alpha.11, 2.0.0-alpha.8.prod, 2.0.0-alpha.8.dev
    npm ERR!
    npm ERR!
    npm ERR! If you need help, you may report this error at:
    npm ERR!

    npm ERR! Please include the following file with any support request:
    npm ERR! C:\zzWork\Omnipot\Main\Source\OmniPot\src\OmniPot\npm-debug.log

    ==================
    Excert from my package.json:
    “dependencies”: {
    “angular2”: “2.0.0-rc.1”,
    “reflect-metadata”: “0.1.3”,
    “rxjs”: “5.0.0-beta.6”,
    “body-parser”: “1.15.1”,
    “bootstrap”: “^3.3.6”,
    “es6-promise”: “3.2.1”,
    “es6-shim”: “^0.35.0”,
    “fancybox”: “^3.0.0”,
    “jquery”: “3.0.0”,
    “ng2-translate”: “2.1.0”,
    “primeng”: “1.0.0-beta.8”,
    “primeui”: “4.1.12”,
    “systemjs”: “0.19.31”,
    “zone.js”: “0.6.12”
    },

  5. The package “angular2”: “2.0.0-rc.1” doesn’t exist on npmjs.org. Use proper angular dependencies as shown in my blog.

  6. Hi Yakov,

    I am following your book, Angular 2 Development with Typescript. I got the Auction app chapter 5 works but there’s an error in Carousel template: Uncaught TypeError: $(…).carousel is not a function.

    If you experience this error, please share solutions. Thanks.

    To get the auction app works, here are a few changes for RC1:
    1. home component template: *ngFor=”let product of (products | filter: [‘title’, filterCriteria])”
    2. application component: constructor(private router: Router){}
    3. product item template: {{ product.title }}
    4. product detail component:
    constructor(params: RouteSegment, productService: ProductService){
    let prodId: number = parseInt(params.getParam(‘productId’));
    ….
    }

  7. Did you happen to try this on SharePoint 2010? It makes IE go down to IE8 (in the master page) and that cause most of the libraries used by Angular 2 to not work properly. There is an Iframe solution but it’s complicated.

    1. Never worked with SharePoint. Consider creating the small shell Angular app (I guess you call it master page) with a link that will use Router.navigateByUrl(your_app_url) and see if it’ll be downgrading your component or not.

  8. Hi, Yakov!
    I updated my project to rc 3 version and install 3 Router and it’s work, thank you!
    So, i have follow question:
    I have read the documentation to Router 3 and found that there have added Gurds.
    And my question is: If I use java as a back-end, what is the best way write security and authentication features, on java, or on Angular ?

  9. Hello, Yakov! Thank you for this blog post, it helped me create my first Angular 2 app from scratch in no time. After I had it running, I replaced “template: `Hello {{ name }}!” in the @Component annotation of the class AppComponent with “templateUrl: ‘./components/intro.html'”. (I have an intro.html file in a sub-directory “components” of the app folder.) My browser only displays “Loading…” instead of my intro.html. What is the correct way to describe the path to the file in templateUrl?

      1. Yes, it works this way, but I think the problem was different: my intro.html contained the , and tags. I removed those now and everything looks fine. Thank you!

      2. Yes, it works this way, but I think the problem was different: my intro.html contained the ‘html’, ‘head’ and ‘body’ tags. I removed those now and everything looks fine. Thank you!

    1. Last year npm was transitioning from higher versions and we wanted to make sure that our projects would require npm 2.14 or newer to be installed on the dev’s computer. Now it can be removed, I guess.

Leave a reply to Yakov Fain Cancel reply