web-dev-qa-db-fra.com

Quelle est la nécessité de SystemJS dans Angular2?

Je suis un débutant complet de Angular et Angular2. Je ne comprends pas comment le flux de travail est structuré. J'ai examiné le exemple de projet présent dans Angular2. site.

Corrigez-moi si je me trompe, mais ce que je sais jusqu'à présent, c'est que tout le TypeScript est transpilé en javascript par le compilateur TypeScript. Ensuite, le javascript compilé correspond à ce qui est exécuté dans le navigateur.

Maintenant, si j'importe les fichiers javascript dans TypeScript à l'aide d'instructions d'importation ES6 telles que:

import { NgModule }      from '@angular/core';

Pourquoi dois-je à nouveau utiliser SystemJS pour les charger -:

map: {
      // our app is within the app folder
      app: 'app',
      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',

Je veux dire, n'est-ce pas contre-productif? L'examen du javascript transcrit des fichiers ts montre que toutes les instructions d'importation sont converties en instructions require (). Premier de tous comment require () fonctionne dans un fichier js ES5 , et ensuite si tel est le cas, que fait SystemJS?.

Cela me déroute vraiment. Toute aide sera fortement appréciée.

50
ng.newbie

Lorsque tsc compile TypeScript en JavaScript, vous vous retrouvez avec un tas de fichiers js sur votre système local. Ils doivent en quelque sorte être chargés dans un navigateur. Étant donné que les navigateurs ne prennent pas encore en charge le chargement de module natif ES6, vous avez deux options: les placer toutes dans votre fichier index.html Dans le bon ordre de dépendances ou vous pouvez utiliser un chargeur pour tout faire à votre place. Vous spécifiez la racine de tous les modules, puis tous les fichiers sont chargés et exécutés par ce chargeur dans le bon ordre de dépendances. Il existe de nombreux chargeurs: requirejs, webpack, systemjs et autres. Dans votre cas particulier, c'est systemjs.

En regardant le fichier javascript transpilé des fichiers ts, il montre que toutes les instructions d'importation sont converties en instructions require ().

Oui, c’est un moyen pour SystemJs de charger des bundles. Il utilise la syntaxe require() et exports car il s'agit de la syntaxe CommonJS pour le chargement des ensembles et vous avez spécifié ce type dans votre tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",

Si vous deviez mettre module:'es6', Vous verriez que dans vos fichiers javascript compilés, les instructions d'importation et d'exportation sont conservées. Cependant, comme mentionné précédemment, vous ne pouvez toujours pas utiliser cette syntaxe car les navigateurs ne la prennent pas en charge de manière native. Si vous deviez mettre module:'AMD', Vous verriez une syntaxe différente qui utilise define(). Je suppose que le chargeur systemjs est préféré dans le didacticiel de démarrage angular2 Car il peut charger tous les types de modules pris en charge par tsc. Cependant, si vous voulez charger des modules en tant que modules es6, Vous devez mettre module: 'system' Dans votre tsconfig.json. C'est un système de module conçu pour adhérer à la norme es6 modules Et utilisé jusqu'à la prise en charge complète de es6 modules Dans les navigateurs.

Comment fonctionne l'installation

Dans votre index.html, Vous ajoutez le script suivant:

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

qui est exécuté lorsque index.html est chargé. La méthode import('app') demande à systemjs de charger le module app mappé au dossier app dans la structure de répertoire de votre projet, comme spécifié par la configuration dans systemjs.config.js:

map: {
    // our app is within the app folder
    app: 'app',

SystemJs recherche le fichier main.js Dans ce dossier. Lorsque app/main.js Est trouvé et chargé dans un navigateur, son code contient l'appel de require:

var app_module_1 = require('./app.module');

et systemjs extrait ensuite le fichier app.module.js du système local. Celui-ci à son tour a ses propres dépendances, comme:

var core_1 = require('@angular/core');

Et le cycle se répète - charger, rechercher des dépendances, les charger et les exécuter. Et c’est ainsi que toutes les dépendances sont résolues, chargées et exécutées dans un navigateur par le systemjs.

Pourquoi les mappages sur les bibliothèques @angulaires principales sont requis

Dans le fichier systemjs.config.ts, Il existe des correspondances avec les modules principaux @angular:

map: {
  ...
  // angular bundles
  '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
  '@angular/common': 'npm:@angular/common/bundles/common.umd.js',

La première chose à comprendre ici est qu’il s’agit de mappages , pas de dépendances. Cela signifie que si aucun de vos fichiers n'importe @angular/core, Il ne sera pas chargé dans un navigateur. Cependant, vous pouvez voir que ce module particulier est importé dans app/app.module.ts:

import { NgModule }      from '@angular/core';

Maintenant, pourquoi les cartographies sont là. Supposons que systemjs charge votre app/app.module.js Dans le navigateur. Il analyse son contenu et trouve ce qui suit:

var core_1 = require('@angular/core');

Maintenant, systemjs comprend qu'il doit résoudre et charger @angular/core. Il passe d'abord par le processus de vérification de mappings, tel que spécifié dans la documentation:

L'option map est similaire aux chemins, mais agit très tôt dans le processus de normalisation. Il vous permet de mapper un alias de module sur un emplacement ou un package.

Je l'appellerais une résolution par un module nommé. Ainsi, il trouve le mappage et substitue @angular/core À node_modules/@angular/core Et c’est là que sont placés les vrais fichiers.

Je pense que systemjs tente d'imiter l'approche utilisée dans node.js, Dans laquelle vous pouvez spécifier un module sans identificateurs de chemin relatif ['/', '../', or './'], Simplement comme ceci require('bar.js') et node.js:

puis Node.js commence au répertoire parent du module actuel, ajoute/node_modules et tente de charger le module à partir de cet emplacement.

Si vous le souhaitez, vous pouvez éviter d'utiliser des mappages nommés et d'importer en utilisant un chemin relatif comme ceci:

import {NgModule} from '../node_modules/@angular/core';

Cependant, cela devrait être fait dans toutes les références à @angular.core Dans les fichiers projet et lib, y compris @angular, Ce qui n'est pas une bonne solution pour le moins.

102