Come raggruppare un'app angolare per la produzione


353

Qual è il metodo migliore per raggruppare Angular (versione 2, 4, 6, ...) per la produzione su un web server live.

Includi la versione angolare tra le risposte in modo da poter tracciare meglio quando passa alle versioni successive.




rc3 ora offre una versione di file in bundle che riduce il numero di richieste da 300+ a circa 40.
Pat M

2
Hey. Odio anche i WebPack e costruisco passaggi in generale. Una specie di eccessivo tentativo di creare un semplice sito Web. Così ho fatto questo: github.com/schungx/angular2-bundle
Stephen Chung,

Grazie Stefano. Questa sarebbe una soluzione semplice per la parte dei fornitori. Spero che questo possa essere offerto e aggiornato ufficialmente. Suppongo che usi qualcosa come Gulp per i file del progetto?
Pat M,

Risposte:


362

2.x, 4.x, 5.x, 6.x, 7.x, 8.x, 9.x (TypeScript) con CLI angolare

Installazione OneTime

  • npm install -g @angular/cli
  • ng new projectFolder crea una nuova applicazione

Bundling Step

  • ng build --prod(eseguito nella riga di comando quando la directory è projectFolder)

    prodbundle di flag per la produzione (consultare la documentazione angolare per l'elenco delle opzioni incluse con il flag di produzione).

  • Comprimi usando la compressione Brotli le risorse usando il seguente comando

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

i bundle vengono generati per impostazione predefinita in projectFolder / dist (/ $ projectFolder per 6)

Produzione

Dimensioni con Angular 9.0.0con CLI 9.0.1e opzione CSS senza routing angolare

  • dist/main-[es-version].[hash].jsApplicazione in bundle [dimensione ES5: 158 KB per la nuova applicazione della CLI angolare vuota, 40 KB compressi].
  • dist/polyfill-[es-version].[hash].bundle.jsle dipendenze polyfill (@angular, RxJS ...) raggruppate [dimensione ES5: 127 KB per la nuova applicazione della CLI angolare vuota, 37 KB compressi].
  • dist/index.html punto di ingresso della domanda.
  • dist/runtime-[es-version].[hash].bundle.js caricatore webpack
  • dist/style.[hash].bundle.css le definizioni di stile
  • dist/assets risorse copiate dalla configurazione degli asset della CLI angolare

Distribuzione

È possibile ottenere un'anteprima dell'applicazione utilizzando il ng serve --prodcomando che avvia un server HTTP locale in modo tale che l'applicazione con file di produzione sia accessibile tramite http: // localhost: 4200 .

Per un utilizzo in produzione, è necessario distribuire tutti i file dalla distcartella nel server HTTP di propria scelta.


Ho ricevuto l'errore durante l'esecuzione di npm install -g angular-cli @ webpack: npm ERR! Includere il seguente file con qualsiasi richiesta di supporto: .... \ npm-debug.log. Sai cosa sta succedendo?
Chong Wang,

2
@chrismarx produce solo un pacchetto che include tutti i componenti con i loro html e stili.
Nicolas Henneaux,

4
Avevo un'applicazione e volevo usare questo metodo, quindi avvio ng init dalla cartella del progetto. Ho fatto il resto dei passaggi ma quando distribuisco le mie applicazioni sembra essere vuoto. L'unica cosa che appare è una "app funziona!" messaggio, c'è un posto dove devo impostare dove prendere i miei file app?
Mautrok,

2
ng-init è stato rimosso dal cli angolare. github.com/angular/angular-cli/issues/5176
Pat M,

2
Alla fine l'ho contrassegnata come risposta accettata. Anche se anche altre soluzioni possono funzionare e fornire anche una maggiore flessibilità (ne ho pubblicato uno sull'utilizzo di Webpack senza CLI). L'uso della CLI angolare è definitivamente quello che dà meno mal di testa. Ho finito per usare la CLI angolare e adattare il mio progetto in modo da poter usare AoT più facilmente.
Pat M,

57

2.0.1 Final utilizzando Gulp (TypeScript - Target: ES5)


Installazione OneTime

  • npm install (eseguito in cmd quando direcory è projectFolder)

Fasi di raggruppamento

  • npm run bundle (eseguito in cmd quando direcory è projectFolder)

    i bundle vengono generati in projectFolder / bundles /

Produzione

  • bundles/dependencies.bundle.js[ dimensione: ~ 1 MB (il più piccolo possibile)]
    • contiene rxjs e dipendenze angolari, non tutti i framework
  • bundles/app.bundle.js[ dimensione: dipende dal tuo progetto , il mio è ~ 0,5 MB ]
    • contiene il tuo progetto

Struttura del file

  • projectFolder / app / (tutti i componenti, direttive, modelli, ecc.)
  • 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 (uguale alla guida di avvio rapido, appena mostrato devDependencies e npm-script richiesti per raggruppare)

{
  "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 (uguale alla guida di avvio rapido , non più disponibile lì)

(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 (appena mostrato la differenza con systemjs.config.json)

var map = {
    'app':                        'dist/app',
  };
  • projectFolder / index.html (produzione) - L'ordine dei tag di script è fondamentale. Posizionare il dist-systemjs.config.jstag dopo i tag bundle consentirebbe comunque l'esecuzione del programma ma il bundle di dipendenze verrebbe ignorato e le dipendenze verrebbero caricate dalla node_modulescartella.

<!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 è dove si trova il bootstrap.

Il meglio che potrei fare ancora :)


2
Ciao, lo script gulp sta creando i bundle, ma non sono sicuro di cosa dovrebbe essere nel file boot.ts? Non sono tutti i file ora nel bundle? Eseguiamo il pacchetto?
Chrismarx,

2
Eh, credo di dover riprovare. Ho provato a passare a builder.buildStatic e ho ricevuto errori da rxjs per non essere caricato come modulo commonjs o amd. Darò un'altra
idea al

1
Non sono anche chiaro come i bundle vengano effettivamente utilizzati in questa configurazione? Mi sembra di riscontrare esattamente gli stessi problemi di @chrismarx qui. Posso creare i bundle, ma poi sembra che tutto sia ancora caricato dalla mia cartella app traspilata e copiata (che si trova in dist / app). Se guardo nel mio pannello di rete, vedo che i file relativi alle mie app vengono effettivamente caricati da lì (componenti, ecc.), Invece di tutto ciò che riguarda l'app proveniente da app.bundle.js. A_Singh, puoi condividere il tuo boot.ts? Sembra che mi manchi qualcosa qui e mi piacerebbe qualche chiarimento.
jbgarr,

1
A_Singh, non vedo come sia d'aiuto. Quando inline-templatesviene eseguito, allinea i modelli, quindi crea una copia di tutte le cartelle e i file delle app in dist/app. Poi, nel dist-systemjs.config.jsmappare appa dist/appche è una cartella che non esisterà se si utilizza la distcartella come root. Non vorresti eseguire la tua app dalla distcartella? E se è così, non avresti una distcartella nidificata nella distcartella principale . Mi manca qualcos'altro qui. Non hai bisogno di dire a systemjs di usare i tuoi file raggruppati e non i soliti file trovati nella dist/appcartella?
jbgarr,

1
Sto riscontrando un problema con la tua soluzione, l'avvio è qualcosa che non esiste qui e quando lo sostituisco con "app" I'va un errore "il modulo non viene definito".
LoïcR

22

Angolare 2 con Webpack (senza impostazione della CLI)

1- Il tutorial del team di Angular2

Il team di Angular2 ha pubblicato un tutorial per l'utilizzo di Webpack

Ho creato e inserito i file dal tutorial in un piccolo progetto seed GitHub . Quindi puoi provare rapidamente il flusso di lavoro.

Istruzioni :

  • npm install

  • inizio npm . Per lo sviluppo. Questo creerà una cartella "dist" virtuale che verrà caricata sul tuo indirizzo localhost.

  • npm run build . Per la produzione. "Ciò creerà una versione fisica della cartella" dist "che può essere inviata a un server Web. La cartella dist è 7,8 MB, ma per caricare la pagina in un browser Web sono necessari solo 234 KB.

2 - Un kit di avvio Webkit

Questo Starter Kit Webpack offre alcune funzionalità di test in più rispetto all'esercitazione di cui sopra e sembra piuttosto popolare.


ciao, è possibile aggiornare il progetto seed con angolare 2.1.0? Il tutorial ora utilizza angular 2.1.0. L'ho seguito e non sono riuscito a farlo funzionare. L'errore è http 404 - impossibile trovare app.component.html.
heq99

Ho aggiornato alla versione 2.1.0 senza problemi. app.component.html viene chiamato da app.component.ts (templateUrl: './app.component.html'). hai entrambi i file nella stessa cartella dell'app?
Pat M,

1
Lo scuotimento degli alberi, la minimizzazione e la compressione possono ridurre notevolmente le dimensioni quando si avvia la produzione. ecco una lettura eccellente con esempio, blog.mgechev.com/2016/06/26/…
Hamzeen Hameem

16

Flusso di lavoro di produzione angolare 2 con builder e gulp di SystemJs

Angular.io ha tutorial di avvio rapido. Ho copiato questo tutorial ed esteso con alcune semplici attività gulp per raggruppare tutto in una cartella dist che può essere copiata sul server e funzionare in questo modo. Ho cercato di ottimizzare tutto per funzionare bene su Jenkis CI, quindi node_modules può essere memorizzato nella cache e non è necessario copiarlo.

Codice sorgente con app di esempio su Github: https://github.com/Anjmao/angular2-production-workflow

Passi per la produzione
  1. I dattiloscritti puliti hanno compilato i file js e la cartella dist
  2. Compilare i file dattiloscritti nella cartella dell'app
  3. Utilizzare il bundler di SystemJs per raggruppare tutto in modo da distribuire la cartella con hash generati per l'aggiornamento della cache del browser
  4. Usa gulp-html-replace per sostituire gli script index.html con le versioni in bundle e copia nella cartella dist
  5. Copia tutto nella cartella delle risorse nella cartella dist

Nodo : Mentre puoi sempre creare il tuo processo di compilazione, ma consiglio vivamente di usare angular-cli, perché ha tutti i flussi di lavoro necessari e funziona perfettamente ora. Lo stiamo già utilizzando in produzione e non abbiamo alcun problema con angular-cli.


Questo è quello che sto cercando. L'app di esempio su github è molto utile. Grazie
Shahriar Hasan Sayeed,

14

Angular CLI 1.xx (funziona con Angular 4.xx, 5.xx)

Questo supporta:

  • Angolare 2.xe 4.x
  • Webpack più recente 2.x
  • Compilatore angolare AoT
  • Routing (normale e pigro)
  • SCSS
  • Raggruppamento di file personalizzato (risorse)
  • Strumenti di sviluppo aggiuntivi (linter, unità e configurazioni di test end-to-end)

Configurazione iniziale

di nuovo project-name --routing

È possibile aggiungere --style=scssper il supporto SASS .scss.

È possibile aggiungere --ng4per l'utilizzo di Angular 4 anziché Angular 2.

Dopo aver creato il progetto, l'interfaccia della riga di comando verrà eseguita automaticamente npm installper te. Se invece vuoi usare Yarn o vuoi semplicemente guardare lo scheletro del progetto senza installarlo, controlla come farlo qui .

Bundle Steps

All'interno della cartella del progetto:

di build -prod

Nella versione corrente è necessario specificare --aotmanualmente, poiché può essere utilizzato in modalità di sviluppo (anche se non è pratico a causa della lentezza).

Questo esegue anche la compilazione AoT per bundle ancora più piccoli (nessun compilatore angolare, invece, ha generato l'output del compilatore). I bundle sono molto più piccoli con AoT se si utilizza Angular 4 poiché il codice generato è più piccolo.
Puoi testare la tua app con AoT in modalità di sviluppo (mappe di origine, nessuna minificazione) e AoT eseguendo ng build --aot.

Produzione

La directory di destinazione predefinita è ./dist, sebbene possa essere cambiata in ./angular-cli.json.

File distribuibili

Il risultato del passaggio di creazione è il seguente:

(Nota: si <content-hash>riferisce all'hash / impronta digitale del contenuto del file che si intende essere un modo di busting della cache, questo è possibile poiché Webpack scrive i scripttag da solo)

  • ./dist/assets
    File copiati così come sono ./src/assets/**
  • ./dist/index.html
    Da ./src/index.html, dopo aver aggiunto gli script webpack ad esso,
    è possibile configurare il file modello sorgente./angular-cli.json
  • ./dist/inline.js
    Caricatore / polyfill per piccoli webpack
  • ./dist/main.<content-hash>.bundle.js
    Il file .js principale contenente tutti gli script .js generati / importati
  • ./dist/styles.<content-hash>.bundle.js
    Quando si utilizzano caricatori Webpack per CSS, che è il modo CLI, vengono caricati tramite JS qui

Nelle versioni precedenti ha anche creato versioni gzip per verificarne le dimensioni e .mapfile sourcemap, ma ciò non accade più poiché le persone continuavano a chiedere di rimuoverle.

Altri file

In alcune altre occasioni, potresti trovare altri file / cartelle indesiderati:

  • ./out-tsc/
    Da ./src/tsconfig.json'soutDir
  • ./out-tsc-e2e/
    Da ./e2e/tsconfig.json'soutDir
  • ./dist/ngfactory/
    Dal compilatore AoT (non configurabile senza biforcare l'interfaccia della riga di comando da beta 16)

È possibile separare la lib angolare e le loro dipendenze dalla mia app?
Dominick Piganell,

Non usare l'interfaccia della riga di comando, che è appositamente progettata per il tremolio dell'albero per funzionare. Ciò sta rimuovendo tutti i moduli Angular EcmaScript che non sono utilizzati nell'applicazione. Esiste un piano per disabilitarlo in modalità dev per la velocità (chiamano le librerie caricate come "DLL"), ma non esiste un piano per separare il risultato finale. Dovrebbe essere realizzabile se stai realizzando le tue cose Webpack senza la CLI.
Meligy,

Come controllare la mia app usando la cartella dist. Come posso ospitare nel mio web server?
raj m

Lo copi semplicemente sul server. È un semplice sito Web statico che può essere servito comunque. Se si utilizza il routing, si potrebbe desiderare di reindirizzare tutte le chiamate al file HTML, però, per quella di controllo angolare docss distribuzione nella sezione di configurazione del server angular.io/docs/ts/latest/guide/...
Meligy

@Meligy cosa succede se rimuovo <content-hash>dai bundle in prod. può causare problemi nell'ottenere l'ultimo pacchetto?
k11k2,

5

Ad oggi trovo ancora il ricettario sulla compilazione anticipata come la migliore ricetta per il raggruppamento di produzione. Puoi trovarlo qui: https://angular.io/docs/ts/latest/cookbook/aot-compiler.html

La mia esperienza con Angular 2 finora è che AoT crea le build più piccole senza quasi nessun tempo di caricamento. E, soprattutto, la domanda qui è: devi solo spedire alcuni file alla produzione.

Ciò sembra essere dovuto al fatto che il compilatore angolare non verrà distribuito con le build di produzione poiché i modelli vengono compilati "Ahead of Time". È anche molto bello vedere il markup del tuo modello HTML trasformato in istruzioni javascript che sarebbe molto difficile decodificare nell'HTML originale.

Ho realizzato un semplice video in cui dimostro le dimensioni del download, il numero di file, ecc. Per un'app Angular 2 in sviluppo dev vs AoT - che puoi vedere qui:

https://youtu.be/ZoZDCgQwnmQ

Troverai il codice sorgente utilizzato nel video qui:

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

Puoi distribuire la tua applicazione angolaregithub usando angular-cli-ghpages

controlla il link per scoprire come distribuire usando questo cli.

il sito Web distribuito verrà archiviato in qualche filiale in githubgenere

GH-pagine

use può clonare il ramo git e usarlo come sito Web statico nel tuo server


1

"Migliore" dipende dallo scenario. Ci sono momenti in cui ti preoccupi solo del singolo bundle più piccolo possibile, ma nelle app di grandi dimensioni potresti dover considerare il caricamento lento. A un certo punto diventa poco pratico servire l'intera app come un unico pacchetto.

In quest'ultimo caso Webpack è generalmente il modo migliore poiché supporta la suddivisione del codice.

Per un singolo bundle prenderei in considerazione Rollup o il compilatore Closure se ti senti coraggioso :-)

Ho creato esempi di tutti i bundler angolari che abbia mai usato qui: http://www.syntaxsuccess.com/viewarticle/angular-production-builds

Il codice è disponibile qui: https://github.com/thelgevold/angular-2-samples

Versione angolare: 4.1.x



0

Prova sotto il comando CLI nella directory del progetto corrente. Creerà un pacchetto di cartelle dist. in modo da poter caricare tutti i file nella cartella dist per le distribuzioni.

di build --prod --aot --base-href.


0

ng serve a servire la nostra applicazione per scopi di sviluppo. E per la produzione? Se esaminiamo il nostro file package.json, possiamo vedere che ci sono script che possiamo usare:

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

Lo script build utilizza la build ng della CLI angolare con il flag --prod. Proviamo ora. Possiamo farlo in due modi:

# usando gli script npm

npm run build

# usando direttamente il cli

ng build --prod

Questa volta ci vengono dati quattro file anziché i cinque. Il flag --prod dice ad Angular di ridurre le dimensioni della nostra applicazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.