Skip to content

Commit 94e9bdc

Browse files
committed
feat(@angular/cli): support sourcemaps and minification in scripts
1 parent cb0cc08 commit 94e9bdc

File tree

6 files changed

+170
-12
lines changed

6 files changed

+170
-12
lines changed

package-lock.json

Lines changed: 75 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"url-loader": "^0.5.7",
101101
"walk-sync": "^0.3.1",
102102
"webpack": "~3.4.1",
103+
"webpack-concat-plugin": "1.4.0",
103104
"webpack-dev-middleware": "^1.11.0",
104105
"webpack-dev-server": "~2.5.1",
105106
"webpack-merge": "^4.1.0",

packages/@angular/cli/models/webpack-configs/common.ts

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import * as webpack from 'webpack';
22
import * as path from 'path';
33
import { GlobCopyWebpackPlugin } from '../../plugins/glob-copy-webpack-plugin';
44
import { NamedLazyChunksWebpackPlugin } from '../../plugins/named-lazy-chunks-webpack-plugin';
5+
import { InsertConcatAssetsWebpackPlugin } from '../../plugins/insert-concat-assets-webpack-plugin';
56
import { extraEntryParser, getOutputHashFormat } from './utils';
67
import { WebpackConfigOptions } from '../webpack-config';
78

9+
const ConcatPlugin = require('webpack-concat-plugin');
810
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
911
const CircularDependencyPlugin = require('circular-dependency-plugin');
1012

@@ -45,12 +47,48 @@ export function getCommonConfig(wco: WebpackConfigOptions) {
4547
// process global scripts
4648
if (appConfig.scripts.length > 0) {
4749
const globalScripts = extraEntryParser(appConfig.scripts, appRoot, 'scripts');
48-
49-
// add entry points and lazy chunks
50-
globalScripts.forEach(script => {
51-
let scriptPath = `script-loader!${script.path}`;
52-
entryPoints[script.entry] = (entryPoints[script.entry] || []).concat(scriptPath);
50+
const globalScriptsByEntry = globalScripts
51+
.reduce((prev: { entry: string, paths: string[], lazy: boolean }[], curr) => {
52+
53+
let existingEntry = prev.find((el) => el.entry === curr.entry);
54+
if (existingEntry) {
55+
existingEntry.paths.push(curr.path);
56+
// All entries have to be lazy for the bundle to be lazy.
57+
existingEntry.lazy = existingEntry.lazy && curr.lazy;
58+
} else {
59+
prev.push({ entry: curr.entry, paths: [curr.path], lazy: curr.lazy });
60+
}
61+
return prev;
62+
}, []);
63+
64+
// Add a new asset for each entry.
65+
globalScriptsByEntry.forEach((script) => {
66+
const hash = hashFormat.chunk !== '' && !script.lazy ? '.[hash]' : '';
67+
// TODO: check supress and packageChunkSort to remove unused stuff.
68+
// TODO: add test for sourcemaps
69+
// TODO: add test for lazy scripts
70+
// TODO: add test for uglification
71+
// TODO: add test for hash
72+
// TODO: common-entry, figure out what to do
73+
// TODO: show them on stats?
74+
extraPlugins.push(new ConcatPlugin({
75+
uglify: buildOptions.target === 'production',
76+
useHash: hashFormat.chunk !== '' && !script.lazy,
77+
sourceMap: buildOptions.sourcemaps,
78+
name: script.entry,
79+
fileName: `${script.entry}.bundle.js`,
80+
// Lazy scripts don't get a hash, otherwise they can't be loaded by name.
81+
fileName: `[${script.entry}]${!script.lazy ? '.[hash]' : ''}.bundle.js`,
82+
filesToConcat: script.paths
83+
}));
5384
});
85+
86+
// Insert all the assets created by ConcatPlugin in the right place in index.html.
87+
extraPlugins.push(new InsertConcatAssetsWebpackPlugin(
88+
globalScriptsByEntry
89+
.filter((el) => !el.lazy)
90+
.map((el) => el.entry)
91+
));
5492
}
5593

5694
// process asset entries

packages/@angular/cli/models/webpack-configs/utils.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,16 @@ export interface HashFormat {
7373
chunk: string;
7474
extract: string;
7575
file: string;
76+
script: string;
7677
}
7778

7879
export function getOutputHashFormat(option: string, length = 20): HashFormat {
7980
/* tslint:disable:max-line-length */
8081
const hashFormats: { [option: string]: HashFormat } = {
81-
none: { chunk: '', extract: '', file: '' },
82-
media: { chunk: '', extract: '', file: `.[hash:${length}]` },
83-
bundles: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: '' },
84-
all: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: `.[hash:${length}]` },
82+
none: { chunk: '', extract: '', file: '' , script: '' },
83+
media: { chunk: '', extract: '', file: `.[hash:${length}]`, script: '' },
84+
bundles: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: '' , script: '.[hash]' },
85+
all: { chunk: `.[chunkhash:${length}]`, extract: `.[contenthash:${length}]`, file: `.[hash:${length}]`, script: '.[hash]' },
8586
};
8687
/* tslint:enable:max-line-length */
8788
return hashFormats[option] || hashFormats['none'];

packages/@angular/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"url-loader": "^0.5.7",
8686
"walk-sync": "^0.3.1",
8787
"webpack": "~3.4.1",
88+
"webpack-concat-plugin": "1.4.0",
8889
"webpack-dev-middleware": "^1.11.0",
8990
"webpack-dev-server": "~2.5.1",
9091
"webpack-merge": "^4.1.0",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Add assets from `ConcatPlugin` to index.html.
2+
3+
export class InsertConcatAssetsWebpackPlugin {
4+
// Priority list of where to insert asset.
5+
private insertAfter = [
6+
/polyfills(\.[0-9a-f]{20})?\.bundle\.js/,
7+
/inline(\.[0-9a-f]{20})?\.bundle\.js/,
8+
];
9+
10+
constructor(private entryNames: string[]) { }
11+
12+
apply(compiler: any): void {
13+
compiler.plugin('compilation', (compilation: any) => {
14+
compilation.plugin('html-webpack-plugin-before-html-generation',
15+
(htmlPluginData: any, callback: any) => {
16+
17+
const fileNames = this.entryNames.map((entryName) => {
18+
const fileName = htmlPluginData.assets.webpackConcat
19+
&& htmlPluginData.assets.webpackConcat[entryName];
20+
21+
if (!fileName) {
22+
// Something went wrong and the asset was not correctly added.
23+
throw new Error(`Cannot find file for ${entryName} script.`);
24+
}
25+
26+
return fileName;
27+
});
28+
29+
let insertAt = 0;
30+
31+
// TODO: try to figure out if there are duplicate bundle names when adding and throw
32+
for (let el of this.insertAfter) {
33+
const jsIdx = htmlPluginData.assets.js.findIndex((js: string) => js.match(el));
34+
if (jsIdx !== -1) {
35+
insertAt = jsIdx + 1;
36+
break;
37+
}
38+
}
39+
40+
htmlPluginData.assets.js.splice(insertAt, 0, ...fileNames);
41+
callback(null, htmlPluginData);
42+
});
43+
});
44+
}
45+
}

0 commit comments

Comments
 (0)