Angular 2 Hello World and the Guinness Book

How a programmer start learning new language or a framework? Right, by writing the Hello World app, which just prints a greeting. If it works, this means that you used the proper syntax and the environent is configured correctly.

This is how Hello World looks in JavaScript running in a browser:

document.write('Hello World');

In Java, Hello World is more verbose:

class helloWorld
{
  public static void main(String args[])
  {
    System.out.println("Hello World");
  }
}

In the Linux Assembly language it’s even more verbose:

 .text

 .global _start
 _start:

 mov $4, %eax 
 mov $1, %ebx 
 mov $msg, %ecx
 mov $msgend-msg, %edx
 int $0x80

 mov $1, %eax 
 mov $0, %ebx 
 int $0x80

 .data

 msg: .ascii "Hello World\n"
 msgend:

Let’s switch from languages to frameworks, which theoretically should let us write less code.

Using jQuery requires you to add to the HTML file one script tag and a couple of lines of JavaScript:

<!DOCTYPE html>  
<html>  
 <head>  
  <meta charset="UTF-8">  
  <title>jQuery</title>  
  <script src="http://code.jquery.com/jquery-2.2.3.min.js"></script>  
 </head>  
 <body>      
  <script>  
   $(document).ready(function() {  
    alert("Hello World!");  
  });   
});    
</script>  

 </body>  
</html>  

Now let’s see two more versions of Hello World:
1) Angular 2 (RC.5) and TypeScript
2) Angular 2 (RC.5) and JavaScript (ES5)

Hello World in TypeScript

The application itself will consist of two files:
index.html and main.ts. I’ll also add the Angular 2 framework with its dependencies, the Typescript compiler, and the SystemJS loader.

The index.html file is the entry point for the application. It will contain the references to the Angular framework, its dependencies, and the main.ts file, which contains the code to bootstrap your application. Some of these references can be located in the configuration file of the module loader.

Loading Angular in the HTML file

The code of the Angular 2 framework consists of modules (one file per module), which are combined into libraries, which are logically grouped into packages, such as `@angular/core`, `@angular/common`, and so on. Your application has to load required packages before the application code.

Let’s create an index.html file, which will start by loading the required Angular scripts, the TypeScript compiler, and the Sy

stemJS module loader. In the first code samples we’ll load these scripts from the npmcdn.com content delivery network (CDN).

<!DOCTYPE html>
<html>
<head>
  <script src="//npmcdn.com/zone.js@0.6.12"></script> // <1>
  <script src="//npmcdn.com/typescript@2.0.0"></script> // <2>
  <script src="//npmcdn.com/reflect-metadata@0.1.3"></script> // <3>
  <script src="//npmcdn.com/systemjs@0.19.36/dist/system.src.js"></script> // <4>
  <script>
    System.config({ // <5>
      transpiler: 'typescript',
      typescriptOptions: {emitDecoratorMetadata: true},
      map: { // <6>
        'rxjs': 'https://npmcdn.com/rxjs@5.0.0-beta.6',

        '@angular/core'                    : 'https://npmcdn.com/@angular/core@2.0.0-rc.5',
        '@angular/common'                  : 'https://npmcdn.com/@angular/common@2.0.0-rc.5',
        '@angular/compiler'                : 'https://npmcdn.com/@angular/compiler@2.0.0-rc.5',
        '@angular/platform-browser'        : 'https://npmcdn.com/@angular/platform-browser@2.0.0-rc.5',
        '@angular/platform-browser-dynamic': 'https://npmcdn.com/@angular/platform-browser-dynamic@2.0.0-rc.5'
      },
      packages: { // <7>
        '@angular/core'                    : {main: 'index.js'},
        '@angular/common'                  : {main: 'index.js'},
        '@angular/compiler'                : {main: 'index.js'},
        '@angular/platform-browser'        : {main: 'index.js'},
        '@angular/platform-browser-dynamic': {main: 'index.js'}
      }
    });
    System.import('main.ts'); // <8>
  </script>
</head>
<body>
  <hello-world></hello-world> // <9>
</body>
</html>

1. Zone.js is a library that powers the change-detection mechanism.

2. The TypeScript compiler transpiles your source code into JavaScript right in the browser.

3. Supports metadata annotations (decorators).

4. The SystemJS library dynamically loads the application code into the browser.

5. Configures SystemJS loader for loading and transpiling TypeScript code.

6. Maps the names of the Angular modules to their CDN locations.

7. Specifies the main script for each Angular module.

8. Instructs SystemJS to load the main module from the main.ts file.

9. The custom HTML element represents the component that’s implemented in main.ts.

When the application is launched, the <hello-world> tag will be replaced with the content of the template from the @Component annotation shown in the next code listing.

The TypeScript file

Now let’s create a main.ts file, which has the TypeScript/Angular code that has three parts:
1. Declare the Hello World component
2. Wrap it into a module
3. Load the module

In the real-world app I’d implement these parts in three separate files, but for simplicity let’s keep all the code of this tiny app in one file.

import {Component} from '@angular/core'; // <1>
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

// Component
@Component({ 
  selector: 'hello-world', // <2>
  template: '<h1>Hello {{ name }}!</h1>' // <3>
})
class HelloWorldComponent { // <4>
  name: string; // <5>

  constructor() {
    this.name = 'Angular'; // <6>
  }
}

// Module
@NgModule({ // <7>
  imports:      [ BrowserModule ],
  declarations: [ HelloWorldComponent ],
  bootstrap:    [ HelloWorldComponent ]
})
export class AppModule { } // <8>

// App bootstrap
platformBrowserDynamic().bootstrapModule(AppModule); // <9>

1. Imports the bootstrap method and the @Component annotation from the corresponding Angular packages, making them available for the application’s code.

2. The @Component annotation placed above the HelloWorldComponent class turns it into an Angular component.
3. The template property defines the HTML markup for rendering this component.

4. The annotated HelloWorldComponent class represents the component.

5. The name property is used in the data-binding expression on the component’s template.

6. Inside the constructor, you initialize the name property with the value Angular 2 bound to the template.

7. The @NgModule annotation declares the content of the module

8. Declare the class representing the module

9. Load the module.

Any app component can be included into HTML file (or a template of another component) by using the tag that matches the component’s name in the selector property of the @Component annotation. Component selectors are similar to CSS selectors, so given the ‘hello-world’ selector, you’d render this component in an HTML page with an element named .

The template contains the data-binding expression {{ name }}, and during runtime Angular will find the name property on your component and replace the data-binding expression in curly braces with a concrete value.

That’s all there is to it. It is verbose. I mean, really!

Let’s see if the good old JavaScript combined with Angular 2 is shorter.

Hello World in ES5

To create applications with ES5, you should use a special Angular bundle distributed in Universal Module Definition (UMD) format (note the umd in the URLs). It publishes all Angular APIs on the global ng object.

The HTML file of the ES5 Angular Hello World application might look like the following:

<!DOCTYPE html>
<html>
<head>
  <script src="//npmcdn.com/zone.js@0.6.12/dist/zone.js"></script>
  <script src="//npmcdn.com/reflect-metadata@0.1.3/Reflect.js"></script>

  <script src="//npmcdn.com/rxjs@5.0.0-beta.6/bundles/Rx.umd.js"></script>
  <script src="//npmcdn.com/@angular/core@2.0.0-rc.5/bundles/core.umd.js"></script>
  <script src="//npmcdn.com/@angular/common@2.0.0-rc.5/bundles/common.umd.js"></script>
  <script src="//npmcdn.com/@angular/compiler@2.0.0-rc.5/bundles/compiler.umd.js"></script>
  <script src="//npmcdn.com/@angular/platform-browser@2.0.0-rc.5/bundles/platform-browser.umd.js"></script>
  <script src="//npmcdn.com/@angular/platform-browser-dynamic@2.0.0-rc.5/bundles/platform-browser-dynamic.umd.js"></script>
</head>
<body>
  <hello-world></hello-world>
  <script src="main.js"></script>
</body>
</html>

Because ES5 doesn’t support the annotations syntax and has no native module system, the main.js file should be written differently from its TypeScript version:

// Component
(function(app) { 
  app.HelloWorldComponent =
      ng.core.Component({
        selector: 'hello-world',
        template: '<h1>Hello {{name}}!</h1>'
      })
      .Class({
        constructor: function() {
          this.name = 'Angular 2';
        }
      });
})(window.app || (window.app = {}));

// Module
(function(app) {
  app.AppModule =
      ng.core.NgModule({
        imports: [ ng.platformBrowser.BrowserModule ],
        declarations: [ app.HelloWorldComponent ],
        bootstrap: [ app.HelloWorldComponent ]
      })
          .Class({
            constructor: function() {}
          });
})(window.app || (window.app = {}));

// App bootstrap
(function(app) {
  document.addEventListener('DOMContentLoaded', function() {
    ng.platformBrowserDynamic
        .platformBrowserDynamic()
        .bootstrapModule(app.AppModule);
  });
})(window.app || (window.app = {}));

The first immediately invoked function expression (IIFE)invokes methods Component() and Class on the global Angular core namespace ng.core. We define and object HelloWorldComponent and the method Component attaches the metadata defining its selector and template. By doing this we turn the JavaScript object into a visual component.

The business logic of your component is coded inside the method Class. In our case we just declared and initialized the property name there that’s bound to the component’s template.

In the second IIFE Then we invoke the method NgModule to create a module that declares our only HelloWorldCompnent and specifies it as a root component by assigning its name to the bootstrap property.

Finally, the third IIFE launches the app by invoking bootstrapModule(), which loads the module, instantiates HelloWorldComponent and attaches it to the browser’s DOM.

So what do you say? The ES5 version of the Angular 2 Hello World app is not shorter that its TypeScript brother.

The main takeaways from this blog are:

1. If you don’t know of more verbose version of Hello World
app, let’s nominate one of the Angular 2 versions to be included into the Guinness World Book of Records 2017.

2. The second reason to be included to the Guinness World Book of Records 2017. I’ve never seen a software that would require a migration guide from one release candidate to another as in https://angular.io/docs/ts/latest/cookbook/rc4-to-rc5.html

3. If you’re writing Hello World type apps, don’t use Angular 2. If you’re writing mid to large Web apps, Angular 2 with TypeScript will decrease time to market of your app.

UPDATE. If you want to create a small deployable version of the app, run it through the Webpack bundler with ahead of time compilation (AOT). The size of the deployable version of HelloWorld will be under 100KB.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s