Skip to content

Commit 2b367be

Browse files
alan-agius4vikerman
authored andcommitted
feat(@angular-devkit/build-angular): deprecate scripts and styles lazy option in favor ofinject
The lazy option inside the script and style option is confusing as this option doesn't lazy load a bundle but rather it doesn't inject/reference the script in the HTML. While this option is an enabler for lazy loading, the users will still need to handle on how how this bundle will be lazy loaded. There are also potential use cases beyond lazy loading for the option. Closes #14814
1 parent 8754ecb commit 2b367be

File tree

13 files changed

+511
-375
lines changed

13 files changed

+511
-375
lines changed

packages/angular/cli/lib/config/schema.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,11 @@
995995
"type": "boolean",
996996
"description": "If the bundle will be lazy loaded.",
997997
"default": false
998+
},
999+
"inject": {
1000+
"type": "boolean",
1001+
"description": "If the bundle will be referenced in the HTML file.",
1002+
"default": true
9981003
}
9991004
},
10001005
"additionalProperties": false,
@@ -1516,6 +1521,11 @@
15161521
"type": "boolean",
15171522
"description": "If the bundle will be lazy loaded.",
15181523
"default": false
1524+
},
1525+
"inject": {
1526+
"type": "boolean",
1527+
"description": "If the bundle will be referenced in the HTML file.",
1528+
"default": true
15191529
}
15201530
},
15211531
"additionalProperties": false,

packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/common.ts

Lines changed: 82 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,9 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
7272
tsConfig.options.target || ScriptTarget.ES5,
7373
);
7474
if ((buildOptions.scriptTargetOverride || tsConfig.options.target) === ScriptTarget.ES5) {
75-
if (buildOptions.es5BrowserSupport ||
76-
(
77-
buildOptions.es5BrowserSupport === undefined &&
78-
buildBrowserFeatures.isEs5SupportNeeded()
79-
)
75+
if (
76+
buildOptions.es5BrowserSupport ||
77+
(buildOptions.es5BrowserSupport === undefined && buildBrowserFeatures.isEs5SupportNeeded())
8078
) {
8179
// The nomodule polyfill needs to be inject prior to any script and be
8280
// outside of webpack compilation because otherwise webpack will cause the
@@ -91,7 +89,7 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
9189
: [noModuleScript];
9290
}
9391

94-
// For differential loading we don't need to generate a seperate polyfill file
92+
// For differential loading we don't need to generate a seperate polyfill file
9593
// because they will be loaded exclusivly based on module and nomodule
9694
const polyfillsChunkName = buildBrowserFeatures.isDifferentialLoadingNeeded()
9795
? 'polyfills'
@@ -120,60 +118,66 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
120118
}
121119

122120
if (buildOptions.profile || process.env['NG_BUILD_PROFILING']) {
123-
extraPlugins.push(new debug.ProfilingPlugin({
124-
outputPath: path.resolve(root, `chrome-profiler-events${targetInFileName}.json`),
125-
}));
121+
extraPlugins.push(
122+
new debug.ProfilingPlugin({
123+
outputPath: path.resolve(root, `chrome-profiler-events${targetInFileName}.json`),
124+
}),
125+
);
126126
}
127127

128128
// determine hashing format
129129
const hashFormat = getOutputHashFormat(buildOptions.outputHashing || 'none');
130130

131131
// process global scripts
132132
if (buildOptions.scripts.length > 0) {
133-
const globalScriptsByBundleName = normalizeExtraEntryPoints(buildOptions.scripts, 'scripts')
134-
.reduce((prev: { bundleName: string, paths: string[], lazy: boolean }[], curr) => {
135-
const bundleName = curr.bundleName;
136-
const resolvedPath = path.resolve(root, curr.input);
137-
const existingEntry = prev.find((el) => el.bundleName === bundleName);
138-
if (existingEntry) {
139-
if (existingEntry.lazy && !curr.lazy) {
140-
// All entries have to be lazy for the bundle to be lazy.
141-
throw new Error(`The ${curr.bundleName} bundle is mixing lazy and non-lazy scripts.`);
142-
}
143-
144-
existingEntry.paths.push(resolvedPath);
145-
} else {
146-
prev.push({
147-
bundleName,
148-
paths: [resolvedPath],
149-
lazy: curr.lazy || false,
150-
});
133+
const globalScriptsByBundleName = normalizeExtraEntryPoints(
134+
buildOptions.scripts,
135+
'scripts',
136+
).reduce((prev: { bundleName: string; paths: string[]; inject: boolean }[], curr) => {
137+
const bundleName = curr.bundleName;
138+
const resolvedPath = path.resolve(root, curr.input);
139+
const existingEntry = prev.find(el => el.bundleName === bundleName);
140+
if (existingEntry) {
141+
if (existingEntry.inject && !curr.inject) {
142+
// All entries have to be lazy for the bundle to be lazy.
143+
throw new Error(
144+
`The ${curr.bundleName} bundle is mixing injected and non-injected scripts.`,
145+
);
151146
}
152147

153-
return prev;
154-
}, []);
148+
existingEntry.paths.push(resolvedPath);
149+
} else {
150+
prev.push({
151+
bundleName,
152+
paths: [resolvedPath],
153+
inject: curr.inject,
154+
});
155+
}
155156

157+
return prev;
158+
}, []);
156159

157160
// Add a new asset for each entry.
158-
globalScriptsByBundleName.forEach((script) => {
161+
globalScriptsByBundleName.forEach(script => {
159162
// Lazy scripts don't get a hash, otherwise they can't be loaded by name.
160-
const hash = script.lazy ? '' : hashFormat.script;
163+
const hash = script.inject ? hashFormat.script : '';
161164
const bundleName = script.bundleName;
162165

163-
extraPlugins.push(new ScriptsWebpackPlugin({
164-
name: bundleName,
165-
sourceMap: scriptsSourceMap,
166-
filename: `${path.basename(bundleName)}${hash}.js`,
167-
scripts: script.paths,
168-
basePath: projectRoot,
169-
}));
166+
extraPlugins.push(
167+
new ScriptsWebpackPlugin({
168+
name: bundleName,
169+
sourceMap: scriptsSourceMap,
170+
filename: `${path.basename(bundleName)}${hash}.js`,
171+
scripts: script.paths,
172+
basePath: projectRoot,
173+
}),
174+
);
170175
});
171176
}
172177

173178
// process asset entries
174179
if (buildOptions.assets) {
175180
const copyWebpackPluginPatterns = buildOptions.assets.map((asset: AssetPatternClass) => {
176-
177181
// Resolve input paths relative to workspace root and add slash at the end.
178182
asset.input = path.resolve(root, asset.input).replace(/\\/g, '/');
179183
asset.input = asset.input.endsWith('/') ? asset.input : asset.input + '/';
@@ -198,8 +202,10 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
198202

199203
const copyWebpackPluginOptions = { ignore: ['.gitkeep', '**/.DS_Store', '**/Thumbs.db'] };
200204

201-
const copyWebpackPluginInstance = new CopyWebpackPlugin(copyWebpackPluginPatterns,
202-
copyWebpackPluginOptions);
205+
const copyWebpackPluginInstance = new CopyWebpackPlugin(
206+
copyWebpackPluginPatterns,
207+
copyWebpackPluginOptions,
208+
);
203209
extraPlugins.push(copyWebpackPluginInstance);
204210
}
205211

@@ -208,20 +214,24 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
208214
}
209215

210216
if (buildOptions.showCircularDependencies) {
211-
extraPlugins.push(new CircularDependencyPlugin({
212-
exclude: /([\\\/]node_modules[\\\/])|(ngfactory\.js$)/,
213-
}));
217+
extraPlugins.push(
218+
new CircularDependencyPlugin({
219+
exclude: /([\\\/]node_modules[\\\/])|(ngfactory\.js$)/,
220+
}),
221+
);
214222
}
215223

216224
if (buildOptions.statsJson) {
217-
extraPlugins.push(new class {
218-
apply(compiler: Compiler) {
219-
compiler.hooks.emit.tap('angular-cli-stats', compilation => {
220-
const data = JSON.stringify(compilation.getStats().toJson('verbose'));
221-
compilation.assets[`stats${targetInFileName}.json`] = new RawSource(data);
222-
});
223-
}
224-
});
225+
extraPlugins.push(
226+
new (class {
227+
apply(compiler: Compiler) {
228+
compiler.hooks.emit.tap('angular-cli-stats', compilation => {
229+
const data = JSON.stringify(compilation.getStats().toJson('verbose'));
230+
compilation.assets[`stats${targetInFileName}.json`] = new RawSource(data);
231+
});
232+
}
233+
})(),
234+
);
225235
}
226236

227237
if (buildOptions.namedChunks) {
@@ -266,15 +276,15 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
266276
: 'rxjs/_esm5/path-mapping';
267277
const rxPaths = require(require.resolve(rxjsPathMappingImport, { paths: [projectRoot] }));
268278
alias = rxPaths(nodeModules);
269-
} catch { }
279+
} catch {}
270280

271281
const extraMinimizers = [];
272282
if (stylesOptimization) {
273283
extraMinimizers.push(
274284
new CleanCssWebpackPlugin({
275285
sourceMap: stylesSourceMap,
276286
// component styles retain their original file name
277-
test: (file) => /\.(?:css|scss|sass|less|styl)$/.test(file),
287+
test: file => /\.(?:css|scss|sass|less|styl)$/.test(file),
278288
}),
279289
);
280290
}
@@ -307,15 +317,18 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
307317
},
308318
// On server, we don't want to compress anything. We still set the ngDevMode = false for it
309319
// to remove dev code, and ngI18nClosureMode to remove Closure compiler i18n code
310-
compress: (buildOptions.platform == 'server' ? {
311-
global_defs: angularGlobalDefinitions,
312-
} : {
313-
pure_getters: buildOptions.buildOptimizer,
314-
// PURE comments work best with 3 passes.
315-
// See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
316-
passes: buildOptions.buildOptimizer ? 3 : 1,
317-
global_defs: angularGlobalDefinitions,
318-
}),
320+
compress:
321+
buildOptions.platform == 'server'
322+
? {
323+
global_defs: angularGlobalDefinitions,
324+
}
325+
: {
326+
pure_getters: buildOptions.buildOptimizer,
327+
// PURE comments work best with 3 passes.
328+
// See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
329+
passes: buildOptions.buildOptimizer ? 3 : 1,
330+
global_defs: angularGlobalDefinitions,
331+
},
319332
// We also want to avoid mangling on server.
320333
...(buildOptions.platform == 'server' ? { mangle: false } : {}),
321334
};
@@ -330,8 +343,10 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
330343
);
331344
}
332345

333-
if (wco.tsConfig.options.target !== undefined &&
334-
wco.tsConfig.options.target >= ScriptTarget.ES2017) {
346+
if (
347+
wco.tsConfig.options.target !== undefined &&
348+
wco.tsConfig.options.target >= ScriptTarget.ES2017
349+
) {
335350
wco.logger.warn(tags.stripIndent`
336351
WARNING: Zone.js does not support native async/await in ES2017.
337352
These blocks are not intercepted by zone.js and will not triggering change detection.
@@ -340,18 +355,13 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration {
340355
}
341356

342357
return {
343-
mode: scriptsOptimization || stylesOptimization
344-
? 'production'
345-
: 'development',
358+
mode: scriptsOptimization || stylesOptimization ? 'production' : 'development',
346359
devtool: false,
347360
profile: buildOptions.statsJson,
348361
resolve: {
349362
extensions: ['.ts', '.tsx', '.mjs', '.js'],
350363
symlinks: !buildOptions.preserveSymlinks,
351-
modules: [
352-
wco.tsConfig.options.baseUrl || projectRoot,
353-
'node_modules',
354-
],
364+
modules: [wco.tsConfig.options.baseUrl || projectRoot, 'node_modules'],
355365
alias,
356366
},
357367
resolveLoader: {

0 commit comments

Comments
 (0)