How to bundle an Angular app for production How to bundle an Angular app for production angular angular

How to bundle an Angular app for production


2 to 11 (TypeScript) with Angular CLI

OneTime Setup

  • npm install -g @angular/cli
  • ng new projectFolder creates a new application

Bundling Step

  • ng build --prod (run in command line when directory is projectFolder)

    flag prod bundle for production (see the Angular documentation for the list of option included with the production flag).

  • Compress using Brotli compression the resources using the following command

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

bundles are generated by default to projectFolder/dist(/$projectFolder for v6+)**

Output

Sizes with Angular 11.2.12 with CLI 11.2.12and option CSS without Angular routing

  • dist/main-[es-version].[hash].js Your application bundled [ ES5 size: 135 KB for new Angular CLI application empty, 38 KB compressed].
  • dist/polyfill-[es-version].[hash].bundle.js the polyfill dependencies (@angular, RxJS...) bundled [ ES5 size: 36 KB for new Angular CLI application empty, 12 KB compressed].
  • dist/index.html entry point of your application.
  • dist/runtime-[es-version].[hash].bundle.js webpack loader
  • dist/style.[hash].bundle.css the style definitions
  • dist/assets resources copied from the Angular CLI assets configuration

Deployment

You can get a preview of your application using the ng serve --prod command that starts a local HTTP server such that the application with production files is accessible using http://localhost:4200. This is not safe to use for production usage.

For a production usage, you have to deploy all the files from the dist folder in the HTTP server of your choice.


2.0.1 Final using Gulp (TypeScript - Target: ES5)


OneTime Setup

  • npm install (run in cmd when direcory is projectFolder)

Bundling Steps

  • npm run bundle (run in cmd when direcory is projectFolder)

    bundles are generated to projectFolder / bundles /

Output

  • bundles/dependencies.bundle.js [ size: ~ 1 MB (as small as possible) ]
    • contains rxjs and angular dependencies, not the whole frameworks
  • bundles/app.bundle.js [ size: depends on your project, mine is ~ 0.5 MB ]
    • contains your project

File Structure

  • projectFolder / app / (all components, directives, templates, 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 (same as Quickstart guide, just shown devDependencies and npm-scripts required to 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 (same as Quickstart guide, not available there anymore)

(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 (just shown the difference with systemjs.config.json)

var map = {    'app':                        'dist/app',  };
  • projectFolder / index.html (production) - The order of the script tags is critical. Placing the dist-systemjs.config.js tag after the bundle tags would still allow the program to run but the dependency bundle would be ignored and dependencies would be loaded from the node_modules folder.

<!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 is where the bootstrap is.

The best I could do yet :)


Angular 2 with Webpack (without CLI setup)

1- The tutorial by the Angular2 team

The Angular2 team published a tutorial for using Webpack

I created and placed the files from the tutorial in a small GitHub seed project. So you can quickly try the workflow.

Instructions:

  • npm install

  • npm start. For development. This will create a virtual "dist" folder that will be livereloaded at your localhost address.

  • npm run build. For production. "This will create a physical "dist" folder version than can be sent to a webserver. The dist folder is 7.8MB but only 234KB is actually required to load the page in a web browser.

2 - A Webkit starter kit

This Webpack Starter Kit offers some more testing features than the above tutorial and seem quite popular.