Wie man eine Angular-Anwendung für die Produktion bündelt

Was ist die beste Methode zum Bündeln von Angular (Version 2, 4, 6, ...) für die Produktion auf einem Live-Webserver.

Bitte geben Sie in Ihren Antworten die Angular-Version an, damit wir besser verfolgen können, wann es zu späteren Versionen kommt.

Lösung

2.x, 4.x, 5.x, 6.x, 7.x, 8.x" (TypeScript) mit Angular CLI

Einmalige Einrichtung

  • npm install -g @angular/cli`
  • ng new projectFolder erstellt eine neue Anwendung

Schritt der Bündelung

  • ng build --prod (in der Kommandozeile ausführen, wenn das Verzeichnis projectFolder ist)

    flag prod bundle for production (siehe die Angular-Dokumentation für die Liste der Optionen, die mit dem production-Flag enthalten sind).

  • Komprimieren Sie die Ressourcen mit Brotli compression mit folgendem Befehl

    for i in dist/*; do brotli $i; done

Bündel werden standardmäßig in projectFolder/dist(/$projectFolder für 6) erzeugt

Ausgabe

Größen mit Angular 8.2.11 mit CLI 8.3.13und Option CSS ohne Angular-Routing

  • dist/main-[es-version].[hash].js` Ihre Anwendung gebündelt [ ES5 Größe: 188 KB für neue Angular CLI Anwendung leer, 44 KB komprimiert].
  • dist/polyfill-[es-version].[hash].bundle.js` die Polyfill-Abhängigkeiten (@angular, RxJS...) gebündelt [ ES5-Größe: 122 KB für neue Angular-CLI-Anwendung leer, 36 KB komprimiert].
  • dist/index.html"-Einstiegspunkt für Ihre Anwendung.
  • dist/runtime-[es-version].[hash].bundle.js` Webpack-Lader
  • dist/style.[hash].bundle.css` die Stildefinitionen
  • dist/assets Ressourcen, die aus der Angular-CLI-Assets-Konfiguration kopiert wurden

Bereitstellung

Sie können eine Vorschau Ihrer Anwendung erhalten, indem Sie den Befehl ng serve --prod verwenden, der einen lokalen HTTP-Server startet, so dass die Anwendung mit Produktionsdateien über http://localhost:4200 zugänglich ist.

Für einen produktiven Einsatz müssen Sie alle Dateien aus dem Ordner dist auf dem HTTP-Server Ihrer Wahl bereitstellen.

Kommentare (38)

2.0.1 Final" mit Gulp (TypeScript - Ziel: ES5)


Einmalige Einrichtung

  • npm install" (in cmd ausführen, wenn das Verzeichnis projectFolder ist)

Schritte zur Bündelung

  • npm run bundle" (in cmd ausführen, wenn das Verzeichnis projectFolder ist)

Bündel werden in projectFolder / bundles / erzeugt

Ausgabe

  • bundles/dependencies.bundle.js` [ Größe: ~ 1 MB (so klein wie möglich) ]
    • enthält rxjs und angular Abhängigkeiten, nicht die ganzen Frameworks
  • bundles/app.bundle.js` [ Größe: hängt von Ihrem Projekt ab, meine ist ~ 0.5 MB ]
    • enthält Ihr Projekt

Struktur der Datei

  • projectFolder / app / (alle Komponenten, Direktiven, Vorlagen, etc.)
  • projectFolder / gulpfile.js


var gulp = require('gulp'),
  tsc = require('gulp-typescript'),
  Builder = require('systemjs-builder'),
  inlineNg2Template = require('gulp-inline-ng2-template');

gulp.task('bundle', ['bundle-app', 'bundle-dependencies'], function(){});

gulp.task('inline-templates', function () {
  return gulp.src('app/**/*.ts')
    .pipe(inlineNg2Template({ useRelativePaths: true, indent: 0, removeLineBreaks: true}))
    .pipe(tsc({
      "target": "ES5",
      "module": "system",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "removeComments": true,
      "noImplicitAny": false
    }))
    .pipe(gulp.dest('dist/app'));
});

gulp.task('bundle-app', ['inline-templates'], function() {
  // optional constructor options
  // sets the baseURL and loads the configuration file
  var builder = new Builder('', 'dist-systemjs.config.js');

  return builder
    .bundle('dist/app/**/* - [@angular/**/*.js] - [rxjs/**/*.js]', 'bundles/app.bundle.js', { minify: true})
    .then(function() {
      console.log('Build complete');
    })
    .catch(function(err) {
      console.log('Build error');
      console.log(err);
    });
});

gulp.task('bundle-dependencies', ['inline-templates'], function() {
  // optional constructor options
  // sets the baseURL and loads the configuration file
  var builder = new Builder('', 'dist-systemjs.config.js');

  return builder
    .bundle('dist/app/**/*.js - [dist/app/**/*.js]', 'bundles/dependencies.bundle.js', { minify: true})
    .then(function() {
      console.log('Build complete');
    })
    .catch(function(err) {
      console.log('Build error');
      console.log(err);
    });
});
  • projectFolder / package.json (wie in der Quickstart-Anleitung, nur mit Angabe von devDependencies und npm-scripts, die zum Bündeln benötigt werden)


{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    ***
     "gulp": "gulp",
     "rimraf": "rimraf",
     "bundle": "gulp bundle",
     "postbundle": "rimraf dist"
  },
  "license": "ISC",
  "dependencies": {
    ***
  },
  "devDependencies": {
    "rimraf": "^2.5.2",
    "gulp": "^3.9.1",
    "gulp-typescript": "2.13.6",
    "gulp-inline-ng2-template": "2.0.1",
    "systemjs-builder": "^0.15.16"
  }
}


(function(global) {

  // map tells the System loader where to look for things
  var map = {
    'app':                        'app',
    'rxjs':                       'node_modules/rxjs',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    '@angular':                   'node_modules/@angular'
  };

  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'app/boot.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { defaultExtension: 'js' }
  };

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

  // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
  packageNames.forEach(function(pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
  });

  var config = {
    map: map,
    packages: packages
  };

  // filterSystemConfig - index.asp's chance to modify config before we register it.
  if (global.filterSystemConfig) { global.filterSystemConfig(config); }

  System.config(config);

})(this);
  • projetcFolder / dist-systemjs.config.js (zeigt gerade den Unterschied zu systemjs.config.json)


var map = {
    'app':                        'dist/app',
  };
  • projectFolder / index.html (Produktion) - *Die Reihenfolge der Skript-Tags ist entscheidend. Wird das Tag "dist-systemjs.config.js" nach den Bundle-Tags platziert, kann das Programm trotzdem ausgeführt werden, aber das Abhängigkeits-Bundle wird ignoriert und die Abhängigkeiten werden aus dem Ordner "node_modules" geladen.





  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>

  Angular





  loading...



<script src="node_modules/core-js/client/shim.min.js"></script>

<script src="node_modules/zone.js/dist/zone.min.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.js"></script>

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

<script src="bundles/dependencies.bundle.js"></script>
<script src="bundles/app.bundle.js"></script>

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

  • projectFolder / app / boot.ts ist der Ort, an dem sich der Bootstrap befindet.

Das Beste, was ich bisher tun konnte :)

Kommentare (14)

Angular 2 Produktionsablauf mit SystemJs Builder und Gulp

Angular.io hat ein Schnellstart-Tutorial. Ich habe dieses Tutorial kopiert und mit ein paar einfachen Gulp-Tasks erweitert, um alles in einem Dist-Ordner zu bündeln, der auf den Server kopiert werden kann und einfach so funktioniert. Ich habe versucht, alles so zu optimieren, dass es auf Jenkis CI gut funktioniert, so dass node_modules gecached werden können und nicht kopiert werden müssen.

Quellcode mit Beispielanwendung auf Github: https://github.com/Anjmao/angular2-production-workflow

Schritte zur Produktion

  1. Säubern der typescripts kompilierten js-Dateien und des dist-Ordners
  2. Kompilieren der typescript-Dateien im app-Ordner
  3. Verwenden Sie den SystemJs-Bundler, um alles in den dist-Ordner zu bündeln, mit generierten Hashes für die Browser-Cache-Aktualisierung
  4. Verwenden Sie gulp-html-replace, um index.html-Skripte durch gebündelte Versionen zu ersetzen und in den dist-Ordner zu kopieren
  5. Kopieren Sie alles im Ordner assets in den Ordner dist

Node: Sie können zwar immer Ihren eigenen Build-Prozess erstellen, aber ich empfehle dringend, angular-cli zu verwenden, da es alle benötigten Workflows enthält und jetzt perfekt funktioniert. Wir sind bereits mit ihm in der Produktion und don't haben keine Probleme mit angular-cli überhaupt.

Kommentare (1)