From 1fe559580faaccf392bf7f02729ab18812438cee Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Tue, 4 Jul 2017 19:07:00 +0100 Subject: [PATCH] feat(@angular/cli): name lazy chunks Before: ``` $ ng build --no-progress Hash: ff03df269349b817eef4 Time: 11202ms chunk {0} 0.chunk.js, 0.chunk.js.map 1.61 kB {1} {3} [rendered] chunk {1} 1.chunk.js, 1.chunk.js.map 1.46 kB {0} {3} [rendered] chunk {2} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 160 kB {6} [initial] [rendered] chunk {3} main.bundle.js, main.bundle.js.map (main) 6.38 kB {5} [initial] [rendered] chunk {4} styles.bundle.js, styles.bundle.js.map (styles) 10.5 kB {6} [initial] [rendered] chunk {5} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.16 MB [initial] [rendered] chunk {6} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered] ``` After: ``` $ ng build --no-progress Hash: 2bc12a89f40f3b4818b5 Time: 9613ms chunk {feature.module} feature.module.chunk.js, feature.module.chunk.js.map 1.46 kB {lazy.module} {main} [rendered] chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry] [rendered] chunk {lazy.module} lazy.module.chunk.js, lazy.module.chunk.js.map 1.61 kB {feature.module} {main} [rendered] chunk {main} main.bundle.js, main.bundle.js.map (main) 6.38 kB {vendor} [initial] [rendered] chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 160 kB {inline} [initial] [rendered] chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 10.5 kB {inline} [initial] [rendered] chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.16 MB [initial] [rendered] ``` Fix #6700 --- .../cli/models/webpack-configs/common.ts | 4 +- .../named-lazy-chunks-webpack-plugin.ts | 38 +++++++++++++++++++ packages/@ngtools/webpack/src/plugin.ts | 6 ++- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 packages/@angular/cli/plugins/named-lazy-chunks-webpack-plugin.ts diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index 99052f62a930..215dd90aa94f 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -1,6 +1,7 @@ import * as webpack from 'webpack'; import * as path from 'path'; import { GlobCopyWebpackPlugin } from '../../plugins/glob-copy-webpack-plugin'; +import { NamedLazyChunksWebpackPlugin } from '../../plugins/named-lazy-chunks-webpack-plugin'; import { extraEntryParser, getOutputHashFormat } from './utils'; import { WebpackConfigOptions } from '../webpack-config'; @@ -109,7 +110,8 @@ export function getCommonConfig(wco: WebpackConfigOptions) { ].concat(extraRules) }, plugins: [ - new webpack.NoEmitOnErrorsPlugin() + new webpack.NoEmitOnErrorsPlugin(), + // new NamedLazyChunksWebpackPlugin(), ].concat(extraPlugins), node: { fs: 'empty', diff --git a/packages/@angular/cli/plugins/named-lazy-chunks-webpack-plugin.ts b/packages/@angular/cli/plugins/named-lazy-chunks-webpack-plugin.ts new file mode 100644 index 000000000000..aeb5a2398ada --- /dev/null +++ b/packages/@angular/cli/plugins/named-lazy-chunks-webpack-plugin.ts @@ -0,0 +1,38 @@ +import * as webpack from 'webpack'; + +// This is just a wrapper around webpack.NamedChunksPlugin to prevent name collisions. +export class NamedLazyChunksWebpackPlugin { + constructor() { + const nameMap = new Map(); + // Append a dot and number if the name already exists. + const getNextName = (baseName: string) => { + let num: number | null = null; + const name = () => num !== null ? `${baseName}.${num}` : baseName; + while (nameMap.has(name())) { + num = num ? num++ : 0; + } + nameMap.set(name(), true); + return name(); + }; + + return new (webpack as any).NamedChunksPlugin(function (chunk: any) { + // Entry chunks have a name already, use it. + if (chunk.name) { + return chunk.name; + } + + // Try to figure out if it's a lazy loaded route. + if (chunk.blocks + && chunk.blocks.length > 0 + && chunk.blocks[0].dependencies + && chunk.blocks[0].dependencies.length > 0 + && chunk.blocks[0].dependencies[0].lazyRouteChunkName + ) { + // lazyRouteChunkName was added by @ngtools/webpack. + return getNextName(chunk.blocks[0].dependencies[0].lazyRouteChunkName); + } + + return null; + }); + } +} diff --git a/packages/@ngtools/webpack/src/plugin.ts b/packages/@ngtools/webpack/src/plugin.ts index 2d2eecf61f76..338cb3b383c7 100644 --- a/packages/@ngtools/webpack/src/plugin.ts +++ b/packages/@ngtools/webpack/src/plugin.ts @@ -310,7 +310,11 @@ export class AotPlugin implements Tapable { .map((key) => { const value = this._lazyRoutes[key]; if (value !== null) { - return new ContextElementDependency(value, key); + const dep = new ContextElementDependency(value, key); + // lazyRouteChunkName is used by webpack.NamedChunksPlugin to give the + // lazy loaded chunk a name. + dep.lazyRouteChunkName = path.basename(key, '.ts'); + return dep; } else { return null; }