103 votes

Comment déployer concrètement une application Angular 2 + Typescript + systemjs ?

Il y a un tutoriel de démarrage rapide sur angular.io qui utilise typescript et systemjs. Maintenant que j'ai fait tourner cette mini-application, comment faire pour créer quelque chose de déployable ? Je n'ai pas trouvé d'informations à ce sujet.

Ai-je besoin d'outils supplémentaires, de paramètres supplémentaires dans System.config ?

(Je sais que je pourrais utiliser webpack et créer un seul bundle.js, mais j'aimerais utiliser systemjs comme il est utilisé dans le tutoriel)

Quelqu'un pourrait-il partager son processus de construction avec cette configuration (Angular 2, TypeScript, systemjs) ?

66voto

thierry templier Points 998

La chose essentielle à comprendre à ce niveau est qu'en utilisant la configuration suivante, vous ne pouvez pas concaténer directement les fichiers JS compilés.

Au niveau de la configuration du compilateur TypeScript :

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "declaration": false,
    "stripInternal": true,
    "module": "system",
    "moduleResolution": "node",
    "noEmitOnError": false,
    "rootDir": ".",
    "inlineSourceMap": true,
    "inlineSources": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

Dans le code HTML

System.config({
  packages: {
    app: {
      defaultExtension: 'js',
      format: 'register'
    }
  }
});

En fait, ces fichiers JS contiennent des modules anonymes. Un module anonyme est un fichier JS qui utilise la fonction System.register mais sans le nom du module comme premier paramètre. C'est ce que le compilateur typescript génère par défaut lorsque systemjs est configuré comme gestionnaire de modules.

Ainsi, pour regrouper tous vos modules dans un seul fichier JS, vous devez utiliser la fonction outFile dans la configuration de votre compilateur TypeScript.

Vous pouvez utiliser ce qui suit dans gulp pour le faire :

const gulp = require('gulp');
const ts = require('gulp-typescript');

var tsProject = ts.createProject('tsconfig.json', {
  typescript: require('typescript'),
  outFile: 'app.js'
});

gulp.task('tscompile', function () {
  var tsResult = gulp.src('./app/**/*.ts')
                     .pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('./dist'));
});

Cela pourrait être combiné avec d'autres traitements :

  • pour uglifier les choses les fichiers TypeScript compilés
  • pour créer un app.js fichier
  • pour créer un vendor.js pour les bibliothèques tierces
  • pour créer un boot.js pour importer le module d'amorçage de l'application. Ce fichier doit être inclus à la fin de la page (lorsque toute la page est chargée).
  • pour mettre à jour le index.html pour prendre en compte ces deux fichiers

Les dépendances suivantes sont utilisées dans les tâches gulp :

  • gulp-concat
  • gulp-html-replace
  • gulp-typescript
  • gulp-uglify

Le texte suivant est un exemple qui peut être adapté.

  • Créer app.min.js fichier

    gulp.task('app-bundle', function () {
      var tsProject = ts.createProject('tsconfig.json', {
        typescript: require('typescript'),
        outFile: 'app.js'
      });
    
      var tsResult = gulp.src('app/**/*.ts')
                       .pipe(ts(tsProject));
    
      return tsResult.js.pipe(concat('app.min.js'))
                    .pipe(uglify())
                    .pipe(gulp.dest('./dist'));
    });
  • Créer vendors.min.js fichier

    gulp.task('vendor-bundle', function() {
      gulp.src([
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/angular2/bundles/angular2-polyfills.js',
        'node_modules/systemjs/dist/system.src.js',
        'node_modules/rxjs/bundles/Rx.js',
        'node_modules/angular2/bundles/angular2.dev.js',
        'node_modules/angular2/bundles/http.dev.js'
      ])
      .pipe(concat('vendors.min.js'))
      .pipe(uglify())
      .pipe(gulp.dest('./dist'));
    });
  • Créer boot.min.js fichier

    gulp.task('boot-bundle', function() {
      gulp.src('config.prod.js')
        .pipe(concat('boot.min.js'))
        .pipe(uglify())
        .pipe(gulp.dest('./dist'));
     });

    El config.prod.js contient simplement les éléments suivants :

     System.import('boot')
        .then(null, console.error.bind(console));
  • Mettre à jour le index.html fichier

    gulp.task('html', function() {
      gulp.src('index.html')
        .pipe(htmlreplace({
          'vendor': 'vendors.min.js',
          'app': 'app.min.js',
          'boot': 'boot.min.js'
        }))
        .pipe(gulp.dest('dist'));
    });

    El index.html ressemble à ce qui suit :

    <html>
      <head>
        <!-- Some CSS -->
    
        <!-- build:vendor -->
        <script src="node_modules/es6-shim/es6-shim.min.js"></script>
        <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
        <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
        <script src="node_modules/systemjs/dist/system.src.js"></script>
        <script src="node_modules/rxjs/bundles/Rx.js"></script>
        <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
        <script src="node_modules/angular2/bundles/http.dev.js"></script>
        <!-- endbuild -->
    
        <!-- build:app -->
        <script src="config.js"></script>
        <!-- endbuild -->
      </head>
    
      <body>
        <my-app>Loading...</my-app>
    
        <!-- build:boot -->
        <!-- endbuild -->
      </body>
    </html>

Notez que le System.import('boot'); doit être fait à la fin du corps pour attendre que tous les composants de votre application soient enregistrés à partir de l'application app.min.js fichier.

Je ne décris pas ici la manière de gérer la minification CSS et HTML.

28voto

Amr ElAdawy Points 180

Vous pouvez utiliser la commande de construction angular2-cli

ng build -prod

https://github.com/angular/angular-cli#creating-a-build

Les constructions créées avec l'option -prod drapeau via ng build -prod o ng serve -prod regrouper toutes les dépendances dans un fichier unique et faire usage de secouer les arbres techniques.

12voto

steely Points 185

Vous pouvez construire un projet Angular 2 (2.0.0-rc.1) en Typescript en utilisant SystemJS avec Gulp y SystemJS-Builder .

Vous trouverez ci-dessous une version simplifiée de la méthode de construction, de regroupement et de réduction de Tour of Heroes en version 2.0.0-rc.1 ( source complète , exemple concret ).

gulpfile.js

var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var typescript = require('gulp-typescript');
var systemjsBuilder = require('systemjs-builder');

// Compile TypeScript app to JS
gulp.task('compile:ts', function () {
  return gulp
    .src([
        "src/**/*.ts",
        "typings/*.d.ts"
    ])
    .pipe(sourcemaps.init())
    .pipe(typescript({
        "module": "system",
        "moduleResolution": "node",
        "outDir": "app",
        "target": "ES5"
    }))
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest('app'));
});

// Generate systemjs-based bundle (app/app.js)
gulp.task('bundle:app', function() {
  var builder = new systemjsBuilder('public', './system.config.js');
  return builder.buildStatic('app', 'app/app.js');
});

// Copy and bundle dependencies into one file (vendor/vendors.js)
// system.config.js can also bundled for convenience
gulp.task('bundle:vendor', function () {
    return gulp.src([
        'node_modules/jquery/dist/jquery.min.js',
        'node_modules/bootstrap/dist/js/bootstrap.min.js',
        'node_modules/es6-shim/es6-shim.min.js',
        'node_modules/es6-promise/dist/es6-promise.min.js',
        'node_modules/zone.js/dist/zone.js',
        'node_modules/reflect-metadata/Reflect.js',
        'node_modules/systemjs/dist/system-polyfills.js',
        'node_modules/systemjs/dist/system.src.js',
      ])
        .pipe(concat('vendors.js'))
        .pipe(gulp.dest('vendor'));
});

// Copy dependencies loaded through SystemJS into dir from node_modules
gulp.task('copy:vendor', function () {
  gulp.src(['node_modules/rxjs/**/*'])
    .pipe(gulp.dest('public/lib/js/rxjs'));

  gulp.src(['node_modules/angular2-in-memory-web-api/**/*'])
    .pipe(gulp.dest('public/lib/js/angular2-in-memory-web-api'));

  return gulp.src(['node_modules/@angular/**/*'])
    .pipe(gulp.dest('public/lib/js/@angular'));
});

gulp.task('vendor', ['bundle:vendor', 'copy:vendor']);
gulp.task('app', ['compile:ts', 'bundle:app']);

// Bundle dependencies and app into one file (app.bundle.js)
gulp.task('bundle', ['vendor', 'app'], function () {
    return gulp.src([
        'app/app.js',
        'vendor/vendors.js'
        ])
    .pipe(concat('app.bundle.js'))
    .pipe(uglify())
    .pipe(gulp.dest('./app'));
});

gulp.task('default', ['bundle']);

system.config.js

var map = {
  'app':                                'app',
  'rxjs':                               'vendor/rxjs',
  'zonejs':                             'vendor/zone.js',
  'reflect-metadata':                   'vendor/reflect-metadata',
  '@angular':                           'vendor/@angular'
};

var packages = {
  'app':                                { main: 'main', defaultExtension: 'js' },
  'rxjs':                               { defaultExtension: 'js' },
  'zonejs':                             { main: 'zone', defaultExtension: 'js' },
  'reflect-metadata':                   { main: 'Reflect', defaultExtension: 'js' }
};

var packageNames = [
  '@angular/common',
  '@angular/compiler',
  '@angular/core',
  '@angular/http',
  '@angular/platform-browser',
  '@angular/platform-browser-dynamic',
  '@angular/router',
  '@angular/router-deprecated',
  '@angular/testing',
  '@angular/upgrade',
];

packageNames.forEach(function(pkgName) {
  packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
});

System.config({
  map: map,
  packages: packages
});

1voto

Shurik Agulyansky Points 369

Voici quelque chose de pratique à regarder : http://mgechev.github.io/angular2-seed/#introduction

1voto

paul Points 9867

La manière la plus simple que j'ai trouvée pour regrouper angular rc1 pour systemJs est d'utiliser gulp y systemjs-builder :

gulp.task('bundle', function () {
    var path = require('path');
    var Builder = require('systemjs-builder');

    var builder = new Builder('/node_modules');

    return builder.bundle([
        '@angular/**/*.js'
        ], 
        'wwwroot/bundle.js', 
        { minify: false, sourceMaps: false })
        .then(function () {
            console.log('Build complete');
        })
        .catch(function (err) {
            console.log('Build error');
            console.log(err);
        });
});

Comme indiqué dans les commentaires, systemJs a actuellement des problèmes lorsqu'il s'agit de regrouper des composants à l'aide de moduleId: module.id

https://github.com/angular/angular/issues/6131

La recommandation actuelle (angular 2 rc1) semble être d'utiliser des chemins explicites, c'est à dire moduleId: '/app/path/'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X