Skip to content

Commit

Permalink
feat(@angular/cli): name lazy chunks
Browse files Browse the repository at this point in the history
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
  • Loading branch information
filipesilva authored and hansl committed Jul 12, 2017
1 parent 27f5d35 commit bcca0d7
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 12 deletions.
4 changes: 3 additions & 1 deletion packages/@angular/cli/models/webpack-configs/common.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion packages/@angular/cli/models/webpack-configs/production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const getProdConfig = function (wco: WebpackConfigOptions) {
new webpack.EnvironmentPlugin({
'NODE_ENV': 'production'
}),
new (<any>webpack).HashedModuleIdsPlugin(),
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.UglifyJsPlugin(<any>{
mangle: { screw_ie8: true },
compress: { screw_ie8: true, warnings: buildOptions.verbose },
Expand Down
41 changes: 41 additions & 0 deletions packages/@angular/cli/plugins/named-lazy-chunks-webpack-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as webpack from 'webpack';


// This just extends webpack.NamedChunksPlugin to prevent name collisions.
export class NamedLazyChunksWebpackPlugin extends webpack.NamedChunksPlugin {
constructor() {
// Append a dot and number if the name already exists.
const nameMap = new Map<string, boolean>();
function getUniqueName(baseName: string) {
let name = baseName;
let num = 0;
while (nameMap.has(name)) {
name = `${baseName}.${num++}`;
}
nameMap.set(name, true);
return name;
}

const nameResolver = (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 getUniqueName(chunk.blocks[0].dependencies[0].lazyRouteChunkName);
}

return null;
};

super(nameResolver);
}
}
4 changes: 3 additions & 1 deletion packages/@angular/cli/plugins/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ module.exports = {
GlobCopyWebpackPlugin: require('../plugins/glob-copy-webpack-plugin').GlobCopyWebpackPlugin,
SuppressExtractedTextChunksWebpackPlugin:
require('../plugins/suppress-entry-chunks-webpack-plugin')
.SuppressExtractedTextChunksWebpackPlugin
.SuppressExtractedTextChunksWebpackPlugin,
NamedLazyChunksWebpackPlugin:
require('../plugins/named-lazy-chunks-webpack-plugin').NamedLazyChunksWebpackPlugin
};
1 change: 1 addition & 0 deletions packages/@angular/cli/tasks/eject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ class JsonWebpackSerializer {
this._addImport('webpack.optimize', 'UglifyJsPlugin');
break;
case angularCliPlugins.BaseHrefWebpackPlugin:
case angularCliPlugins.NamedLazyChunksWebpackPlugin:
case angularCliPlugins.SuppressExtractedTextChunksWebpackPlugin:
this._addImport('@angular/cli/plugins/webpack', plugin.constructor.name);
break;
Expand Down
10 changes: 10 additions & 0 deletions packages/@angular/cli/webpack-custom-typings.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as webpack from 'webpack';

declare module 'webpack' {
export class NamedChunksPlugin {
constructor(nameResolver: (chunk: any) => string | null);
}
export class HashedModuleIdsPlugin {
constructor();
}
}
6 changes: 5 additions & 1 deletion packages/@ngtools/webpack/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
16 changes: 13 additions & 3 deletions tests/e2e/tests/misc/lazy-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,27 @@ export default function() {
.then(() => ng('build'))
.then(() => oldNumberOfFiles = readdirSync('dist').length)
.then(() => ng('generate', 'module', 'lazy', '--routing'))
.then(() => ng('generate', 'module', 'too/lazy', '--routing'))
.then(() => addImportToModule('src/app/app.module.ts', oneLine`
RouterModule.forRoot([{ path: "lazy", loadChildren: "app/lazy/lazy.module#LazyModule" }]),
RouterModule.forRoot([{ path: "lazy1", loadChildren: "./lazy/lazy.module#LazyModule" }])
RouterModule.forRoot([{ path: "lazy1", loadChildren: "./lazy/lazy.module#LazyModule" }]),
RouterModule.forRoot([{ path: "lazy2", loadChildren: "./too/lazy/lazy.module#LazyModule" }])
`, '@angular/router'))
.then(() => ng('build'))
.then(() => readdirSync('dist').length)
.then(currentNumberOfDistFiles => {
.then(() => readdirSync('dist'))
.then((distFiles) => {
const currentNumberOfDistFiles = distFiles.length;
if (oldNumberOfFiles >= currentNumberOfDistFiles) {
throw new Error('A bundle for the lazy module was not created.');
}
oldNumberOfFiles = currentNumberOfDistFiles;

if (!distFiles.includes('lazy.module.chunk.js')){
throw new Error('The bundle for the lazy module did not have a name.');
}
if (!distFiles.includes('lazy.module.0.chunk.js')){
throw new Error('The bundle for the lazy module did not use a unique name.');
}
})
// verify System.import still works
.then(() => writeFile('src/app/lazy-file.ts', ''))
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4355,16 +4355,16 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"

rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
rimraf@2, rimraf@^2.2.8, rimraf@~2.2.6:
version "2.2.8"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"

rimraf@^2.5.1, rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"

rimraf@~2.2.6:
version "2.2.8"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582"

ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
Expand Down

0 comments on commit bcca0d7

Please sign in to comment.