Comment regrouper une application Angular pour la production


353

Quelle est la meilleure méthode pour regrouper Angular (version 2, 4, 6, ...) pour la production sur un serveur Web en direct.

Veuillez inclure la version angulaire dans les réponses afin que nous puissions mieux suivre son évolution vers les versions ultérieures.




rc3 propose désormais une version de fichiers groupés qui réduit le nombre de demandes de 300+ à environ 40.
Pat M

2
Hey. Je déteste également les WebPack et les étapes de construction en général. Sorte de surpuissant pour simplement essayer de créer un site Web simple. Ainsi j'ai fait ceci: github.com/schungx/angular2-bundle
Stephen Chung

Merci Stephen. Ce serait une solution simple pour la partie fournisseurs. En espérant que cela puisse être officiellement proposé et mis à jour. Je suppose que vous utilisez quelque chose comme Gulp pour les fichiers du projet?
Pat M

Réponses:


362

2.x, 4.x, 5.x, 6.x, 7.x, 8.x, 9.x (TypeScript) avec Angular CLI

Configuration OneTime

  • npm install -g @angular/cli
  • ng new projectFolder crée une nouvelle application

Étape de regroupement

  • ng build --prod(exécuté en ligne de commande lorsque le répertoire est projectFolder)

    prodensemble de drapeaux pour la production (voir la documentation angulaire pour la liste des options incluses avec le drapeau de production).

  • Compresser à l'aide de la compression Brotli des ressources à l'aide de la commande suivante

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

les bundles sont générés par défaut dans projectFolder / dist (/ $ projectFolder pour 6)

Production

Tailles avec Angular 9.0.0avec CLI 9.0.1et option CSS sans routage angulaire

  • dist/main-[es-version].[hash].jsVotre application intégrée [taille ES5: 158 Ko pour la nouvelle application CLI Angular vide, 40 Ko compressés].
  • dist/polyfill-[es-version].[hash].bundle.jsles dépendances polyfill (@angular, RxJS ...) regroupées [taille ES5: 127 Ko pour la nouvelle application CLI Angular vide, 37 Ko compressés].
  • dist/index.html point d'entrée de votre candidature.
  • dist/runtime-[es-version].[hash].bundle.js chargeur de webpack
  • dist/style.[hash].bundle.css les définitions de style
  • dist/assets ressources copiées à partir de la configuration des actifs de la CLI angulaire

Déploiement

Vous pouvez obtenir un aperçu de votre application à l'aide de la ng serve --prodcommande qui démarre un serveur HTTP local de sorte que l'application avec les fichiers de production soit accessible à l'aide de http: // localhost: 4200 .

Pour une utilisation en production, vous devez déployer tous les fichiers du distdossier sur le serveur HTTP de votre choix.


J'ai eu l'erreur lors de l'exécution de npm install -g angular-cli @ webpack: npm ERR! Veuillez inclure le fichier suivant avec toute demande d'assistance: .... \ npm-debug.log. Savez-vous ce qui se passe?
Chong Wang

2
@chrismarx il ne produit qu'un seul bundle comprenant tous les composants avec leur html et leurs styles.
Nicolas Henneaux

4
J'avais une application et je voulais utiliser cette méthode, donc je lance ng init depuis le dossier du projet. J'ai fait le reste des étapes mais lorsque je déploie mes applications, il semble être vide. La seule chose qui apparaît est une «application fonctionne! message, y a-t-il un endroit où je dois définir où prendre mes fichiers d'application?
mautrok

2
ng-init a été retiré du cli angulaire. github.com/angular/angular-cli/issues/5176
Pat M

2
J'ai finalement marqué cela comme la réponse acceptée. Bien que d'autres solutions puissent également fonctionner et même offrir une flexibilité supplémentaire (j'en ai publié une sur l'utilisation de Webpack sans CLI). L'utilisation de la CLI angulaire est définitivement celle qui donne le moins de maux de tête. J'ai fini par utiliser Angular CLI et à adapter mon projet pour pouvoir utiliser AoT plus facilement.
Pat M

57

2.0.1 Final en utilisant Gulp (TypeScript - Cible: ES5)


Configuration OneTime

  • npm install (exécuté en cmd lorsque le répertoire est projectFolder)

Étapes de regroupement

  • npm run bundle (exécuté en cmd lorsque le répertoire est projectFolder)

    les bundles sont générés dans projectFolder / bundles /

Production

  • bundles/dependencies.bundle.js[ taille: ~ 1 Mo (aussi petit que possible)]
    • contient des rxjs et des dépendances angulaires, pas tous les frameworks
  • bundles/app.bundle.js[ taille: dépend de votre projet , le mien est ~ 0,5 Mo ]
    • contient votre projet

Structure des fichiers

  • projectFolder / app / (tous les composants, directives, modèles, 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 (identique au guide de démarrage rapide , juste les devDependencies et les scripts npm requis pour être regroupés)

{
  "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"
  }
}
  • projectFolder / systemjs.config.js (identique au guide de démarrage rapide , qui n'y est plus disponible)

(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 (vient de montrer la différence avec systemjs.config.json)

var map = {
    'app':                        'dist/app',
  };
  • projectFolder / index.html (production) - L'ordre des balises de script est critique. Placer la dist-systemjs.config.jsbalise après les balises de bundle permettrait toujours au programme de s'exécuter mais le bundle de dépendances serait ignoré et les dépendances seraient chargées à partir du node_modulesdossier.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
  <base href="/"/>
  <title>Angular</title>
  <link rel="stylesheet" type="text/css" href="style.css"/>
</head>
<body>

<my-app>
  loading...
</my-app>

<!-- Polyfill(s) for older browsers -->
<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>
<!-- Project Bundles. Note that these have to be loaded AFTER the systemjs.config 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>
</body>
</html>
  • projectFolder / app / boot.ts est l'emplacement du bootstrap.

Le mieux que j'ai pu faire encore :)


2
Salut, le script gulp crée les bundles, mais je ne sais pas ce qui devrait être dans le fichier boot.ts? Tous les fichiers ne sont-ils pas maintenant dans le bundle? Exécutons-nous le bundle?
chrismarx

2
Huh, je suppose que je dois réessayer. J'ai essayé de passer à builder.buildStatic et j'ai reçu des erreurs de rxjs sur le fait de ne pas être chargé en tant que module commonjs ou amd. Je vais essayer encore une fois votre suggestion
chrismarx

1
Je ne sais pas non plus comment les bundles sont réellement utilisés dans cette configuration? Il semble que je rencontre les mêmes problèmes que @chrismarx ici. Je peux créer les bundles, mais il semble que tout soit toujours en cours de chargement depuis mon dossier d'application transpilé et copié (situé dans dist / app). Si je regarde dans mon panneau réseau, je peux voir que mes fichiers liés à l'application sont en train d'être chargés à partir de là (composants, etc.), au lieu de tout ce qui concerne l'application provenant de app.bundle.js. A_Singh, pouvez-vous partager vos boot.ts? Il semble que je manque quelque chose ici et j'aimerais avoir des éclaircissements.
jbgarr

1
A_Singh, je ne vois pas comment cela aide. Lorsqu'il inline-templatesest exécuté, il insère les modèles, puis crée une copie de tous les dossiers et fichiers d'application sur dist/app. Ensuite, dist-systemjs.config.jsvous mappez appvers dist/appun dossier qui n'existera pas si vous utilisez le distdossier en tant que root. Souhaitez-vous pas exécuter votre application à partir du distdossier? Et si c'est le cas, vous n'auriez pas de distdossier imbriqué dans le distdossier racine . Je dois manquer quelque chose d'autre ici. N'avez-vous pas besoin de dire à systemjs d'utiliser vos fichiers groupés et non les fichiers habituels trouvés dans le dist/appdossier?
jbgarr

1
Je rencontre un problème avec votre solution, le démarrage est quelque chose qui n'existe pas ici, et quand je le remplace par "app" I'va an error "le module n'est pas défini".
LoïcR

22

Angular 2 avec Webpack (sans configuration CLI)

1- Le tutoriel de l'équipe Angular2

L'équipe Angular2 a publié un tutoriel pour l'utilisation de Webpack

J'ai créé et placé les fichiers du tutoriel dans un petit projet de départ GitHub . Vous pouvez donc essayer rapidement le workflow.

Instructions :

  • installation de npm

  • npm start . Pour le developpement. Cela créera un dossier virtuel "dist" qui sera chargé à votre adresse d'hôte local.

  • npm run build . Pour la production. "Cela créera une version physique du dossier" dist "qui peut être envoyée à un serveur Web. Le dossier dist fait 7,8 Mo, mais seulement 234 Ko sont réellement nécessaires pour charger la page dans un navigateur Web.

2 - Un kit de démarrage Webkit

Ce kit de démarrage Webpack offre plus de fonctionnalités de test que le tutoriel ci-dessus et semble assez populaire.


salut, est-il possible de mettre à jour le projet seed avec angular 2.1.0? Le tutoriel utilise maintenant angulaire 2.1.0. Je l'ai suivi et n'ai pas pu le faire fonctionner. L'erreur est http 404 - impossible de trouver app.component.html.
heq99

J'ai mis à jour vers angular 2.1.0 sans problème. app.component.html est appelé depuis app.component.ts (templateUrl: './app.component.html'). vous avez les deux fichiers dans le même dossier d'application?
Pat M

1
La secousse des arbres, la minification et le Gzipping peuvent réduire considérablement la taille lorsque vous allez en production. voici une excellente lecture avec exemple, blog.mgechev.com/2016/06/26/…
Hamzeen Hameem

16

Workflow de production angulaire 2 avec SystemJs Builder et Gulp

Angular.io propose un didacticiel de démarrage rapide. J'ai copié ce tutoriel et étendu avec quelques tâches de gulp simples pour tout regrouper dans le dossier dist qui peut être copié sur le serveur et fonctionner comme ça. J'ai essayé d'optimiser tout pour bien fonctionner sur Jenkis CI, donc node_modules peut être mis en cache et n'a pas besoin d'être copié.

Code source avec exemple d'application sur Github: https://github.com/Anjmao/angular2-production-workflow

Étapes de la production
  1. Nettoyer les fichiers js compilés et les dossiers dist
  2. Compiler des fichiers dactylographiés dans le dossier de l'application
  3. Utilisez le bundle SystemJs pour tout regrouper dans un dossier dist avec des hachages générés pour l'actualisation du cache du navigateur
  4. Utilisez gulp-html-replace pour remplacer les scripts index.html par les versions groupées et copiez-les dans le dossier dist
  5. Copiez tout dans le dossier des ressources dans le dossier dist

Node : Bien que vous puissiez toujours créer votre propre processus de construction, mais je recommande fortement d'utiliser angular-cli, car il a tous les workflows nécessaires et il fonctionne parfaitement maintenant. Nous l'utilisons déjà en production et nous n'avons aucun problème avec angular-cli.


Voilà ce que je recherche. Un exemple d'application sur github est très utile. Merci
Shahriar Hasan Sayeed

14

CLI angulaire 1.xx (fonctionne avec Angular 4.xx, 5.xx)

Cela prend en charge:

  • Angulaire 2.x et 4.x
  • Dernière Webpack 2.x
  • Compilateur angulaire AoT
  • Routage (normal et paresseux)
  • SCSS
  • Regroupement de fichiers personnalisés (actifs)
  • Outils de développement supplémentaires (configurations de tests linter, unitaires et de bout en bout)

La configuration initiale

ng new project-name --routing

Vous pouvez ajouter --style=scsspour la prise en charge de SASS .scss.

Vous pouvez ajouter --ng4pour utiliser Angular 4 au lieu d'Angular 2.

Après avoir créé le projet, la CLI s'exécutera automatiquement npm installpour vous. Si vous souhaitez utiliser Yarn à la place, ou si vous voulez simplement regarder le squelette du projet sans installer, vérifiez comment le faire ici .

Étapes du bundle

Dans le dossier du projet:

ng build -prod

Dans la version actuelle, vous devez spécifier --aotmanuellement, car il peut être utilisé en mode développement (bien que ce ne soit pas pratique en raison de la lenteur).

Cela effectue également la compilation AoT pour des bundles encore plus petits (pas de compilateur angulaire, à la place, une sortie de compilateur générée). Les bundles sont beaucoup plus petits avec AoT si vous utilisez Angular 4 car le code généré est plus petit.
Vous pouvez tester votre application avec AoT en mode développement (sourcemaps, pas de minification) et AoT en exécutantng build --aot .

Production

Le répertoire de sortie par défaut est ./dist, bien qu'il puisse être modifié dans ./angular-cli.json.

Fichiers déployables

Le résultat de l'étape de génération est le suivant:

(Remarque: <content-hash>fait référence au hachage / empreinte digitale du contenu du fichier qui est censé être un moyen de contournement du cache, cela est possible car Webpack écrit les scriptbalises lui-même)

  • ./dist/assets
    Fichiers copiés tels quels ./src/assets/**
  • ./dist/index.html
    De ./src/index.html, après y avoir ajouté des scripts webpack, le
    fichier de modèle source est configurable dans./angular-cli.json
  • ./dist/inline.js
    Petit chargeur de webpack / polyfill
  • ./dist/main.<content-hash>.bundle.js
    Le fichier .js principal contenant tous les scripts .js générés / importés
  • ./dist/styles.<content-hash>.bundle.js
    Lorsque vous utilisez des chargeurs Webpack pour CSS, qui est la méthode CLI, ils sont chargés via JS ici

Dans les anciennes versions, il créait également des versions gzippées pour vérifier leur taille et des .mapfichiers sourcemaps, mais cela ne se produit plus car les gens continuaient à demander de les supprimer.

Autres fichiers

Dans certaines autres occasions, vous pouvez trouver d'autres fichiers / dossiers indésirables:

  • ./out-tsc/
    De ./src/tsconfig.json« soutDir
  • ./out-tsc-e2e/
    De ./e2e/tsconfig.json« soutDir
  • ./dist/ngfactory/
    Depuis le compilateur AoT (non configurable sans bifurquer la CLI à partir de la beta 16)

Est-il possible de séparer la bibliothèque angulaire et leurs dépendances de mon application?
Dominick Piganell

Ne pas utiliser la CLI, qui est exprès pour que la secousse d'arbre fonctionne. Cela supprime tous les modules Angular EcmaScript qui ne sont pas utilisés dans votre application. Il existe un plan pour désactiver cela en mode dev pour la vitesse (ils appellent les bibliothèques chargées telles quelles "DLL"), mais aucun plan pour séparer le résultat final. Cela devrait être réalisable si vous lancez vos propres trucs Webpack sans l'interface CLI.
Meligy

Comment vérifier mon application à l'aide du dossier dist. Comment puis-je héberger sur mon serveur Web?
raj m

Vous venez de le copier sur le serveur. C'est un site Web statique simple qui peut être servi de toute façon. Si vous utilisez le routage, vous voudrez peut-être rediriger tous les appels vers le fichier HTML, pour cela, vérifiez la documentation de déploiement angulaire sur la section de configuration du serveur angular.io/docs/ts/latest/guide/…
Meligy

@Meligy que faire si je supprime <content-hash>des bundles dans prod. cela peut entraîner des problèmes lors de l'obtention du dernier pack?
k11k2

5

À ce jour, je trouve toujours le livre de recettes de la compilation anticipée comme la meilleure recette pour le regroupement de la production. Vous pouvez le trouver ici: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

Mon expérience avec Angular 2 jusqu'à présent est que l'AoT crée les plus petites versions avec presque aucun temps de chargement. Et le plus important, car la question est ici - vous n'avez besoin d'envoyer que quelques fichiers en production.

Cela semble être dû au fait que le compilateur Angular ne sera pas livré avec les versions de production car les modèles sont compilés "Ahead of Time". Il est également très cool de voir votre balisage de modèle HTML transformé en instructions javascript qui seraient très difficiles à inverser dans le code HTML d'origine.

J'ai fait une vidéo simple où je montre la taille du téléchargement, le nombre de fichiers, etc. pour une application Angular 2 dans la version dev vs AoT - que vous pouvez voir ici:

https://youtu.be/ZoZDCgQwnmQ

Vous trouverez le code source utilisé dans la vidéo ici:

https://github.com/fintechneo/angular2-templates


3
        **Production build with

         - Angular Rc5
         - Gulp
         - typescripts 
         - systemjs**

        1)con-cat all js files  and css files include on index.html using  "gulp-concat".
          - styles.css (all css concat in this files)
          - shims.js(all js concat in this files)

        2)copy all images and fonts as well as html files  with gulp task to "/dist".

        3)Bundling -minify angular libraries and app components mentioned in systemjs.config.js file.
         Using gulp  'systemjs-builder'

            SystemBuilder = require('systemjs-builder'),
            gulp.task('system-build', ['tsc'], function () {
                var builder = new SystemBuilder();
                return builder.loadConfig('systemjs.config.js')
                    .then(function () {
                        builder.buildStatic('assets', 'dist/app/app_libs_bundle.js')
                    })
                    .then(function () {
                        del('temp')
                    })
            });


    4)Minify bundles  using 'gulp-uglify'

jsMinify = require('gulp-uglify'),

    gulp.task('minify', function () {
        var options = {
            mangle: false
        };
        var js = gulp.src('dist/app/shims.js')
            .pipe(jsMinify())
            .pipe(gulp.dest('dist/app/'));
        var js1 = gulp.src('dist/app/app_libs_bundle.js')
            .pipe(jsMinify(options))
            .pipe(gulp.dest('dist/app/'));
        var css = gulp.src('dist/css/styles.min.css');
        return merge(js,js1, css);
    });

5) In index.html for production 

    <html>
    <head>
        <title>Hello</title>

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

       <link rel="stylesheet" href="app/css/styles.min.css" />   
       <script type="text/javascript" src="app/shims.js"></script>  
       <base href="https://stackoverflow.com/">
    </head>
     <body>
    <my-app>Loading...</my-app>
     <script type="text/javascript" src="app/app_libs_bundle.js"></script> 
    </body>

    </html>

 6) Now just copy your dist folder to '/www' in wamp server node need to copy node_modules in www.

2

Vous pouvez déployer votre application angulaire en githubutilisant angular-cli-ghpages

consultez le lien pour savoir comment déployer à l'aide de ce cli.

le site Web déployé sera stocké dans une succursale en githubgénéral

pages-gh

l'utilisation peut cloner la branche git et l'utiliser comme un site Web statique sur votre serveur


1

"Meilleur" dépend du scénario. Il y a des moments où vous ne vous souciez que du plus petit ensemble unique possible, mais dans les grandes applications, vous devrez peut-être envisager un chargement paresseux. À un moment donné, il devient impossible de servir l'application entière en un seul paquet.

Dans ce dernier cas, Webpack est généralement le meilleur moyen car il prend en charge le fractionnement de code.

Pour un seul paquet, je considérerais Rollup, ou le compilateur Closure si vous vous sentez courageux :-)

J'ai créé des échantillons de tous les bundlers angulaires que j'ai jamais utilisés ici: http://www.syntaxsuccess.com/viewarticle/angular-production-builds

Le code peut être trouvé ici: https://github.com/thelgevold/angular-2-samples

Version angulaire: 4.1.x



0

Veuillez essayer ci-dessous la commande CLI dans le répertoire de projet actuel. Il créera un ensemble de dossiers dist. afin que vous puissiez télécharger tous les fichiers dans le dossier dist pour les déploiements.

ng build --prod --aot --base-href.


0

ng serve fonctionne pour servir notre application à des fins de développement. Et pour la production? Si nous regardons notre fichier package.json, nous pouvons voir qu'il existe des scripts que nous pouvons utiliser:

"scripts": {
  "ng": "ng",
  "start": "ng serve",
  "build": "ng build --prod",
  "test": "ng test",
  "lint": "ng lint",
  "e2e": "ng e2e"
},

Le script de génération utilise la génération ng de la CLI angulaire avec l'indicateur --prod. Essayons ça maintenant. Nous pouvons le faire de deux manières:

# en utilisant les scripts npm

npm run build

# en utilisant directement le cli

ng build --prod

Cette fois, on nous donne quatre fichiers au lieu des cinq. L'indicateur --prod indique à Angular de réduire la taille de notre application.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.