01. Initialisation : Installation des librairies et compilation avec TypeScript

J’ai divisé l’initialisation du projet en deux parties. Dans cette première partie, nous allons nous concentrer sur la récupération des librairies Angular 2 et la compilation du TypeScript pour créer une première page.

Les dépendances

Angular 2 est développé de manière modulaire et suis les préceptes modernes en terme d’architecture JavaScript. On ne va donc pas simplement installer un fichier JS mais récupérer plusieurs dépendances qui seront chargées en fonction de nos besoins. Initions donc un nouveau projet, pour cela créons un nouveau répertoire et utilisons NPM :

$> npm init –y

Pour ceux qui ne connaisse pas NPM, vous devrez en préambule regarder la leçon sur les bases de NPM.

Pour connaître la liste des dépendances et leur version, le plus simple est d’aller dans la documentation d’Angular et de récupérer la liste dans la section quickstart Nous ne récupérons que les dépendances pour le projet; pour les dépendances de développement nous en installerons 3 :

Ce qui nous donnera le package.json suivant :

{
  "name": "showtheque-angular2",
  "version": "1.0.0",
  "description": "ShowTheque avec Angular 2",
  "main": "index.html",
  "scripts": {
  },
  "dependencies": {
    "@angular/common": "~2.1.1",
    "@angular/compiler": "~2.1.1",
    "@angular/core": "~2.1.1",
    "@angular/forms": "~2.1.1",
    "@angular/http": "~2.1.1",
    "@angular/platform-browser": "~2.1.1",
    "@angular/platform-browser-dynamic": "~2.1.1",
    "@angular/router": "~3.1.1",
    "@angular/upgrade": "~2.1.1",
    "core-js": "^2.4.1",
    "reflect-metadata": "^0.1.8",
    "rxjs": "5.0.0-beta.12",
    "systemjs": "0.19.39",
    "zone.js": "^0.6.25"
  },
  "devDependencies": {
    "lite-server": "^2.2.2",
    "typescript": "^2.0.6",
    "typings": "1.5.0"
  }
}

Il ne reste plus qu'a récupérer tous ces packages avec NPM :

$> npm install

Comme nous travaillons en local nous allons devoir ajouter dans la section scripts, les 3 dépendances de développement qui fonctionnent en ligne de commande:

{
    "scripts": {
        "tsc": "tsc",
        "typings": "typings",
        "server": "lite-server"
    }
}

Configuration des modules

Comme je le disais, nous n’allons pas inclure directement Angular mais utiliser un système de module qui permettra de charger les portions d’Angular dont nous avons besoin. Pour cela, nous utiliserons comme outil systemjs. Pour ce faire, il faut créer un fichier de configuration systemjs.config.js dont le contenu peut être également récupéré depuis la documentation d’Angular :

(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: 'app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
      '@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',

      // others libraries
      'rxjs':                      'npm:rxjs'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });
})(this);

En résumé, on indique à systemjs où récupérer les différents modules, puis on déclare une application app dont le point d'entrée sera par la suite contenu dans un fichier main.js.

Création de la page principale et ajout des librairies

Créons à la racine, une page HTML qui sera le point d’entrée de notre application index.html dans laquelle on ajoute, d’une part les librairies ne faisant pas partie des modules déclarés dans systemjs, puis la configuration systemjs.config.js que nous avons précédemment créée, et pour terminer un petit script pour lancer l’application.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ShowTheque Angular 2</title>
</head>
<body>

    <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/systemjs/dist/system.src.js"></script>

    <script src="systemjs.config.js"></script>

    <script>
        System.import('app').catch(function(err){console.error(err)});
    </script>

</body>
</html>

Configuration de TypeScript

Pour la configuration de TypeScript, nous allons encore une fois nous inspirer de la documentation d’Angular pour créer notre tsconfig.json. J’y apporte plusieurs modifications, notamment l’ajout d’une propriété outDir car je mettrais les sources de l’application dans un répertoire src et les fichiers compilés dans un répertoire app.

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "outDir": "app"
  },
  "exclude": [
      "node_modules"
  ]
}

Pour terminer, nous allons installer un fichier de définition de type pour la librairie core-js afin que TypeScript soit capable de compiler nos futures sources. Pour cela, nous utilisons l’outil typings précédemment installé, qui fonctionne un peu comme NPM. Il va créer un fichier typings.json contenant la liste des dépendances. Elles se téléchargent dans un répertoire typings (équivalent du node_modules).

$> npm run typings install dt~core-js -- --global --save

L'argument install car nous installons une dépendance. dt représente la source, ici le répertoire classique DefinitelyTyped puis le nom du type recherché.

Création du premier composant

Maintenant que tout est prêt, créons notre premier composant afin d’afficher une première page fonctionnant avec Angular 2. Pour ceux qui pratique déjà AngularJS 1 les controller n’existent plus, ils sont remplacés par des component. Pour créer un component, nous devons créer une classe et la décorer avec l’attribut @Component.

// src/app.component.ts
import { Component } from '@angular/core';

@Component({
    selector:'app',
    templateUrl: './app/app.component.html'
})
export class AppComponent
{

}

Ic, on importe l’objet Component depuis Angular et on décore la class avec. Dans ce décorateur on utilise deux propriétés :

Créons de suite ce fichier, qui pour le moment contiendra simplement un titre et un texte.

<!--src/app.component.html-->
<h1>Home</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Numquam cumque beatae a doloribus? Doloribus vero aperiam, laboriosam ipsum, ut eum voluptatum ad. Nisi et, veniam doloremque minima maiores non ut tempore eligendi, modi possimus corporis odio dolor aliquam ducimus harum hic ullam aspernatur repellendus nemo praesentium temporibus natus architecto iusto?<p/>

Création du module principal

Pour utiliser le composant précédemment créé, nous devons au préalable, créer un module. Les modules permettent de décomposer une application en plusieurs parties indépendantes. Il doit également y avoir un module principal qui fait appel à ces sous-modules. Créons le module central de notre application qui utilisera le composant AppComponent.

// src/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

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

Un module est une simple classe décorée avec @NgModule. Dans ce décorateur il y a 4 propriétés principales:

Lancement de l'application

Il ne reste plus que deux étapes. Tout d’abord, placer notre composant central dans notre page index.html; pour cela nous plaçons une balise correspondant à la propriété selector

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ShowTheque Angular 2</title>
</head>
<body>

    <app>loading...</app>

    <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/systemjs/dist/system.src.js"></script>
    <script src="systemjs.config.js"></script>
    <script>
        System.import('app').catch(function(err){ console.error(err); });
    </script>

</body>
</html>

Puis, nous créons un fichier qui lancera notre application; il sera appelé par SystemJS, c’est le main.js dont nous avons parlé au début.

// src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Démarrage

Ne reste plus qu'a compiler le TypeScript et lancer l'application avec NPM:

$> npm run tsc
$> npm run server

C’est terminé pour cette première étape. Nous mettrons en place dans la prochaine leçon, Gulp, afin de compiler automatiquement nos sources et rafraichir le navigateur à chaque modification. Nous ajouterons également les librairies de style.