Come raggruppare un’app Angolare per la produzione

Vorrei tenere traccia e aggiornare in questo thread il metodo migliore (e spero il più semplice) per raggruppare Angular (versione 2, 4, …) per la produzione su un server web live.

Si prega di includere la versione angular all’interno delle risposte in modo da poter monitorare meglio quando si passa alle versioni successive.

2.x, 4.x, 5.x, 6.x (TypeScript) con CLI angular

Setup OneTime

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

Fase di raggruppamento

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

    flag prod bundle for production (consultare la documentazione Angular per l’elenco delle opzioni incluse nel flag di produzione).

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

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

i bundle sono generati di default in projectFolder / dist (/ $ projectFolder per 6)

Produzione

Taglie con Angular 6.1.5 con CLI 6.1.5

  • dist/main.[hash].bundle.js tua applicazione ha raggruppato [dimensione: 168 KB per la nuova applicazione Angular CLI vuota, 41 KB compressi].
  • dist/polyfill.[hash].bundle.js le dipendenze polyfill (@angular, RxJS …) in bundle [dimensione: 58 KB per la nuova applicazione Angular CLI vuota, 17 KB compressi].
  • dist/index.html punto di ingresso della tua applicazione.
  • dist/inline.[hash].bundle.js loader del webpack
  • dist/style.[hash].bundle.css le definizioni di stile
  • dist/assets risorse copiate dalla configurazione delle risorse della CLI angular

Distribuzione

È ansible ottenere un’anteprima dell’applicazione utilizzando il comando ng serve --prod che avvia un server HTTP locale in modo tale che l’applicazione con i file di produzione sia accessibile utilizzando http: // localhost: 4200 .

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

2.0.1 Final usando Gulp (TypeScript – Target: ES5)


Setup OneTime

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

Fasi di raggruppamento

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

    i pacchetti vengono generati per projectFolder / bundle /

Produzione

  • bundles/dependencies.bundle.js [ dimensione: ~ 1 MB (il più piccolo ansible)]
    • contiene rxjs e dipendenze angolari, non l’intero framework
  • bundles/app.bundle.js [ dimensione: dipende dal 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 (come nella guida di Quickstart , ha appena mostrato devDependencies e npm-scripts necessari per il bundle)
 { "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 (come per la guida di Quickstart , non disponibile più 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 (production) – L’ordine dei tag di script è fondamentale. Posizionando il tag dist-systemjs.config.js dopo che i tag del bundle avrebbero comunque permesso al programma di funzionare, il bundle delle dipendenze sarebbe stato ignorato e le dipendenze sarebbero state caricate dalla cartella node_modules .
       Angular     loading...              
  • projectFolder / app / boot.ts è dove si trova il bootstrap.

Il meglio che potevo fare ancora 🙂

Angular 2 con Webpack (senza configurazione 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 seme GitHub . In questo modo puoi provare rapidamente il stream di lavoro.

Istruzioni :

  • installazione di npm

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

  • npm esegue build . Per la produzione. “Ciò creerà una versione della cartella” dist “fisica che può essere inviata a un server Web. La cartella dist è 7.8MB ma in realtà è necessario solo 234 KB per caricare la pagina in un browser web.

2 – Un kit di avvio Webkit

Questo Starter Kit di Webpack offre alcune funzionalità di test in più rispetto all’esercitazione precedente e sembra molto popolare.

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

Angular.io ha un tutorial di avvio rapido. Ho copiato questo tutorial ed esteso con alcune semplici attività di gulp per unire tutto alla cartella dist che può essere copiata sul server e funzionare proprio così. Ho cercato di ottimizzare tutto per funzionare bene su CI di Jenkis, 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. Pulisci i dattiloscritti compilati con i file js e la cartella dist
  2. Compilare i file dattiloscritti nella cartella dell’app
  3. Usa il bundler di SystemJs per raggruppare tutto in una cartella dist con gli hash generati per l’aggiornamento della cache del browser
  4. Usa gulp-html-replace per sostituire gli script index.html con versioni in bundle e copia nella cartella dist
  5. Copia tutto all’interno della cartella delle risorse nella cartella dist

Node : 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.

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

Questo supporta:

  • Angolare 2.xe 4.x
  • Ultimo Webpack 2.x
  • Compilatore angular AoT
  • Routing (normale e pigro)
  • SCSS
  • Raggruppamento di file personalizzato (risorse)
  • Ulteriori strumenti di sviluppo (configurazioni di test linter, unità e end-to-end)

Configurazione iniziale

 ng nuovo nome-progetto --routing

Puoi aggiungere --style=scss per il supporto SSS .scss.

Puoi aggiungere --ng4 per usare Angular 4 invece di Angular 2.

Dopo aver creato il progetto, la CLI eseguirà automaticamente l’ npm install per te. Se invece vuoi usare Filato, o semplicemente vuoi guardare lo scheletro del progetto senza installare, controlla come farlo qui .

Fasi del pacchetto

All’interno della cartella del progetto:

 ng build -prod

Alla versione attuale è necessario specificare: --aot manualmente, perché può essere utilizzato in modalità sviluppo (sebbene ciò non sia pratico a causa della lentezza).

Questo esegue anche la compilazione AoT per i bundle ancora più piccoli (nessun compilatore angular, invece, ha generato l’output del compilatore). I pacchetti sono molto più piccoli con AoT se si utilizza Angular 4 in quanto il codice generato è più piccolo.
Puoi testare la tua app con AoT in modalità sviluppo (sourcemaps, no minification) e AoT eseguendo ng build --aot .

Produzione

La ./dist output predefinita è ./dist , sebbene possa essere modificata in ./angular-cli.json .

File distribuibili

Il risultato del passo di costruzione è il seguente:

(Nota: riferisce all’hash / impronta digitale dei contenuti del file che è destinato a essere un modo di busting della cache, questo è ansible poiché Webpack scrive i tag dello script da solo)

  • ./dist/assets
    I file copiati così come sono da ./src/assets/**
  • ./dist/index.html
    Da ./src/index.html , dopo aver aggiunto gli script webpack
    Il file modello di origine è configurabile in ./angular-cli.json
  • ./dist/inline.js
    Piccolo caricatore webpack / polyfill
  • ./dist/main..bundle.js
    Il file .js principale contenente tutti gli script .js generati / importati
  • ./dist/styles..bundle.js
    Quando si usano i caricatori di Webpack per CSS, che è il modo CLI, vengono caricati tramite JS qui

Nelle versioni precedenti creava anche versioni compresse con gzip per controllarne le dimensioni e i file .map sourcemaps, ma ciò non accade più perché la gente continuava a chiedere di rimuoverli.

Altri file

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

  • ./out-tsc/
    Da ./src/tsconfig.json outDir
  • ./out-tsc-e2e/
    Da. / outDir / outDir ‘s outDir
  • ./dist/ngfactory/
    Dal compilatore AoT (non configurabile senza biforcazione della CLI a partire dalla beta 16)

Ad oggi, trovo ancora il libro di ricette di Ahead-of-Time Compilation 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 la cosa più importante, in questo caso, riguarda la questione: è sufficiente spedire alcuni file alla produzione.

Questo sembra essere dovuto al fatto che il compilatore Angolare non verrà spedito con i build di produzione man mano che i template vengono compilati “Ahead of Time”. È anche molto interessante vedere il markup del modello HTML trasformato in istruzioni javascript che sarebbe molto difficile da decodificare nel codice HTML originale.

Ho realizzato un semplice video in cui mostro le dimensioni del download, il numero di file ecc. Per un’app Angular 2 in dev vs AoT build – che puoi vedere qui:

https://youtu.be/ZoZDCgQwnmQ

Qui troverai il codice sorgente utilizzato nel video:

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

  **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   Hello        Loading...    6) Now just copy your dist folder to '/www' in wamp server node need to copy node_modules in www. 

È ansible distribuire la propria applicazione angular su github usando angular-cli-ghpages

controlla il link per scoprire come utilizzare questo cli.

il sito Web implementato verrà archiviato in alcuni rami in github genere

GH-pagine

uso può clonare il ramo git e usarlo come sito web statico sul tuo server

“Best” dipende dallo scenario. Ci sono momentjs in cui ti interessa solo il bundle singolo più piccolo, ma nelle app di grandi dimensioni potresti dover considerare il caricamento pigro. Ad un certo punto diventa poco pratico servire l’intera app come un unico pacchetto.

In quest’ultimo caso, Webpack è in genere il modo migliore in quanto supporta la divisione del codice.

Per un singolo pacchetto considererei Rollup o il compilatore Closure se ti senti coraggioso 🙂

Ho creato campioni di tutti i pacchetti angolari che ho mai usato qui: http://www.syntaxsuccess.com/viewarticle/angular-production-builds

Il codice può essere trovato qui: https://github.com/thelgevold/angular-2-samples

Versione angular: 4.1.x

È sufficiente configurare angular 4 con webpack 3 entro un minuto dal momento in cui il bundle ENV di sviluppo e produzione sarà pronto senza alcun problema, basta seguire il seguente documento github

https://github.com/roshan3133/angular2-webpack-starter