@angular-devkit/build-angular 13.1.0-next.2 → 13.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +22 -22
- package/src/babel/presets/application.d.ts +4 -2
- package/src/babel/presets/application.js +2 -12
- package/src/babel/webpack-loader.js +21 -13
- package/src/builders/browser/index.js +3 -2
- package/src/builders/dev-server/index.js +31 -2
- package/src/builders/extract-i18n/ivy-extract-loader.js +4 -1
- package/src/utils/bundle-calculator.d.ts +6 -7
- package/src/utils/bundle-calculator.js +3 -1
- package/src/utils/environment-options.d.ts +0 -1
- package/src/utils/environment-options.js +1 -4
- package/src/utils/i18n-options.d.ts +16 -10
- package/src/utils/i18n-options.js +46 -37
- package/src/utils/index-file/augment-index-html.d.ts +5 -1
- package/src/utils/index-file/augment-index-html.js +38 -5
- package/src/utils/read-tsconfig.js +1 -4
- package/src/webpack/configs/common.js +18 -20
- package/src/webpack/configs/dev-server.js +6 -8
- package/src/webpack/configs/styles.js +21 -10
- package/src/webpack/plugins/named-chunks-plugin.d.ts +17 -0
- package/src/webpack/plugins/named-chunks-plugin.js +49 -0
- package/src/webpack/utils/helpers.d.ts +2 -0
- package/src/webpack/utils/helpers.js +17 -1
- package/src/webpack/utils/stats.d.ts +2 -1
- package/src/webpack/utils/stats.js +67 -35
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular-devkit/build-angular",
|
|
3
|
-
"version": "13.1.
|
|
3
|
+
"version": "13.1.1",
|
|
4
4
|
"description": "Angular Webpack Build Facade",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"typings": "src/index.d.ts",
|
|
7
7
|
"builders": "builders.json",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@ampproject/remapping": "1.0.
|
|
10
|
-
"@angular-devkit/architect": "0.1301.
|
|
11
|
-
"@angular-devkit/build-webpack": "0.1301.
|
|
12
|
-
"@angular-devkit/core": "13.1.
|
|
9
|
+
"@ampproject/remapping": "1.0.2",
|
|
10
|
+
"@angular-devkit/architect": "0.1301.1",
|
|
11
|
+
"@angular-devkit/build-webpack": "0.1301.1",
|
|
12
|
+
"@angular-devkit/core": "13.1.1",
|
|
13
13
|
"@babel/core": "7.16.0",
|
|
14
14
|
"@babel/generator": "7.16.0",
|
|
15
15
|
"@babel/helper-annotate-as-pure": "7.16.0",
|
|
@@ -19,19 +19,19 @@
|
|
|
19
19
|
"@babel/preset-env": "7.16.4",
|
|
20
20
|
"@babel/runtime": "7.16.3",
|
|
21
21
|
"@babel/template": "7.16.0",
|
|
22
|
-
"@discoveryjs/json-ext": "0.5.
|
|
23
|
-
"@ngtools/webpack": "13.1.
|
|
22
|
+
"@discoveryjs/json-ext": "0.5.6",
|
|
23
|
+
"@ngtools/webpack": "13.1.1",
|
|
24
24
|
"ansi-colors": "4.1.1",
|
|
25
25
|
"babel-loader": "8.2.3",
|
|
26
26
|
"babel-plugin-istanbul": "6.1.1",
|
|
27
27
|
"browserslist": "^4.9.1",
|
|
28
28
|
"cacache": "15.3.0",
|
|
29
29
|
"circular-dependency-plugin": "5.2.2",
|
|
30
|
-
"copy-webpack-plugin": "
|
|
31
|
-
"core-js": "3.19.
|
|
32
|
-
"critters": "0.0.
|
|
30
|
+
"copy-webpack-plugin": "10.0.0",
|
|
31
|
+
"core-js": "3.19.3",
|
|
32
|
+
"critters": "0.0.15",
|
|
33
33
|
"css-loader": "6.5.1",
|
|
34
|
-
"esbuild-wasm": "0.
|
|
34
|
+
"esbuild-wasm": "0.14.2",
|
|
35
35
|
"glob": "7.2.0",
|
|
36
36
|
"https-proxy-agent": "5.0.0",
|
|
37
37
|
"inquirer": "8.2.0",
|
|
@@ -41,38 +41,38 @@
|
|
|
41
41
|
"less-loader": "10.2.0",
|
|
42
42
|
"license-webpack-plugin": "4.0.0",
|
|
43
43
|
"loader-utils": "3.2.0",
|
|
44
|
-
"mini-css-extract-plugin": "2.4.
|
|
44
|
+
"mini-css-extract-plugin": "2.4.5",
|
|
45
45
|
"minimatch": "3.0.4",
|
|
46
46
|
"open": "8.4.0",
|
|
47
47
|
"ora": "5.4.1",
|
|
48
48
|
"parse5-html-rewriting-stream": "6.0.1",
|
|
49
49
|
"piscina": "3.1.0",
|
|
50
|
-
"postcss": "8.
|
|
50
|
+
"postcss": "8.4.4",
|
|
51
51
|
"postcss-import": "14.0.2",
|
|
52
|
-
"postcss-loader": "6.2.
|
|
52
|
+
"postcss-loader": "6.2.1",
|
|
53
53
|
"postcss-preset-env": "6.7.0",
|
|
54
54
|
"regenerator-runtime": "0.13.9",
|
|
55
55
|
"resolve-url-loader": "4.0.0",
|
|
56
56
|
"rxjs": "6.6.7",
|
|
57
|
-
"sass": "1.
|
|
58
|
-
"sass-loader": "12.
|
|
57
|
+
"sass": "1.44.0",
|
|
58
|
+
"sass-loader": "12.4.0",
|
|
59
59
|
"semver": "7.3.5",
|
|
60
60
|
"source-map-loader": "3.0.0",
|
|
61
|
-
"source-map-support": "0.5.
|
|
61
|
+
"source-map-support": "0.5.21",
|
|
62
62
|
"stylus": "0.55.0",
|
|
63
63
|
"stylus-loader": "6.2.0",
|
|
64
64
|
"terser": "5.10.0",
|
|
65
65
|
"text-table": "0.2.0",
|
|
66
66
|
"tree-kill": "1.2.2",
|
|
67
67
|
"tslib": "2.3.1",
|
|
68
|
-
"webpack": "5.
|
|
69
|
-
"webpack-dev-middleware": "5.2.
|
|
70
|
-
"webpack-dev-server": "4.
|
|
68
|
+
"webpack": "5.65.0",
|
|
69
|
+
"webpack-dev-middleware": "5.2.2",
|
|
70
|
+
"webpack-dev-server": "4.6.0",
|
|
71
71
|
"webpack-merge": "5.8.0",
|
|
72
72
|
"webpack-subresource-integrity": "5.0.0"
|
|
73
73
|
},
|
|
74
74
|
"optionalDependencies": {
|
|
75
|
-
"esbuild": "0.
|
|
75
|
+
"esbuild": "0.14.2"
|
|
76
76
|
},
|
|
77
77
|
"peerDependencies": {
|
|
78
78
|
"@angular/compiler-cli": "^13.0.0 || ^13.1.0-next",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"ng-packagr": "^13.0.0 || ^13.1.0-next",
|
|
83
83
|
"protractor": "^7.0.0",
|
|
84
84
|
"tailwindcss": "^2.0.0",
|
|
85
|
-
"typescript": "
|
|
85
|
+
"typescript": ">=4.4.3 <4.6"
|
|
86
86
|
},
|
|
87
87
|
"peerDependenciesMeta": {
|
|
88
88
|
"@angular/localize": {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* Use of this source code is governed by an MIT-style license that can be
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
|
+
import type { ɵParsedTranslation } from '@angular/localize/private';
|
|
8
9
|
import type { makeEs2015TranslatePlugin, makeEs5TranslatePlugin, makeLocalePlugin } from '@angular/localize/tools';
|
|
9
10
|
export declare type DiagnosticReporter = (type: 'error' | 'warning' | 'info', message: string) => void;
|
|
10
11
|
/**
|
|
@@ -22,8 +23,9 @@ export interface ApplicationPresetOptions {
|
|
|
22
23
|
i18n?: {
|
|
23
24
|
locale: string;
|
|
24
25
|
missingTranslationBehavior?: 'error' | 'warning' | 'ignore';
|
|
25
|
-
translation?:
|
|
26
|
-
|
|
26
|
+
translation?: Record<string, ɵParsedTranslation>;
|
|
27
|
+
translationFiles?: string[];
|
|
28
|
+
pluginCreators: I18nPluginCreators;
|
|
27
29
|
};
|
|
28
30
|
angularLinker?: {
|
|
29
31
|
shouldLink: boolean;
|
|
@@ -60,28 +60,18 @@ function createI18nDiagnostics(reporter) {
|
|
|
60
60
|
})();
|
|
61
61
|
return diagnostics;
|
|
62
62
|
}
|
|
63
|
-
function createI18nPlugins(locale, translation, missingTranslationBehavior, diagnosticReporter,
|
|
64
|
-
// TODO_ESM: Make `pluginCreators` required once `@angular/localize` is published with the `tools` entry point
|
|
65
|
-
pluginCreators) {
|
|
63
|
+
function createI18nPlugins(locale, translation, missingTranslationBehavior, diagnosticReporter, pluginCreators) {
|
|
66
64
|
const diagnostics = createI18nDiagnostics(diagnosticReporter);
|
|
67
65
|
const plugins = [];
|
|
66
|
+
const { makeEs5TranslatePlugin, makeEs2015TranslatePlugin, makeLocalePlugin } = pluginCreators;
|
|
68
67
|
if (translation) {
|
|
69
|
-
const { makeEs2015TranslatePlugin,
|
|
70
|
-
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
|
|
71
|
-
} = pluginCreators !== null && pluginCreators !== void 0 ? pluginCreators : require('@angular/localize/src/tools/src/translate/source_files/es2015_translate_plugin');
|
|
72
68
|
plugins.push(makeEs2015TranslatePlugin(diagnostics, translation, {
|
|
73
69
|
missingTranslation: missingTranslationBehavior,
|
|
74
70
|
}));
|
|
75
|
-
const { makeEs5TranslatePlugin,
|
|
76
|
-
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
|
|
77
|
-
} = pluginCreators !== null && pluginCreators !== void 0 ? pluginCreators : require('@angular/localize/src/tools/src/translate/source_files/es5_translate_plugin');
|
|
78
71
|
plugins.push(makeEs5TranslatePlugin(diagnostics, translation, {
|
|
79
72
|
missingTranslation: missingTranslationBehavior,
|
|
80
73
|
}));
|
|
81
74
|
}
|
|
82
|
-
const { makeLocalePlugin,
|
|
83
|
-
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
|
|
84
|
-
} = pluginCreators !== null && pluginCreators !== void 0 ? pluginCreators : require('@angular/localize/src/tools/src/translate/source_files/locale_plugin');
|
|
85
75
|
plugins.push(makeLocalePlugin(locale));
|
|
86
76
|
return plugins;
|
|
87
77
|
}
|
|
@@ -41,6 +41,7 @@ async function requiresLinking(path, source) {
|
|
|
41
41
|
}
|
|
42
42
|
return needsLinking(path, source);
|
|
43
43
|
}
|
|
44
|
+
// eslint-disable-next-line max-lines-per-function
|
|
44
45
|
exports.default = (0, babel_loader_1.custom)(() => {
|
|
45
46
|
const baseOptions = Object.freeze({
|
|
46
47
|
babelrc: false,
|
|
@@ -65,13 +66,10 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
65
66
|
};
|
|
66
67
|
// Analyze file for linking
|
|
67
68
|
if (await requiresLinking(this.resourcePath, source)) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const linkerBabelModule = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel');
|
|
73
|
-
linkerPluginCreator = linkerBabelModule.createEs2015LinkerPlugin;
|
|
74
|
-
}
|
|
69
|
+
// Load ESM `@angular/compiler-cli/linker/babel` using the TypeScript dynamic import workaround.
|
|
70
|
+
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
71
|
+
// changed to a direct dynamic import.
|
|
72
|
+
linkerPluginCreator !== null && linkerPluginCreator !== void 0 ? linkerPluginCreator : (linkerPluginCreator = (await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli/linker/babel')).createEs2015LinkerPlugin);
|
|
75
73
|
customOptions.angularLinker = {
|
|
76
74
|
shouldLink: true,
|
|
77
75
|
jitMode: aot !== true,
|
|
@@ -104,20 +102,24 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
104
102
|
// During the transition, this will always attempt to load the entry point for each file.
|
|
105
103
|
// This will only occur during prerelease and will be automatically corrected once the new
|
|
106
104
|
// entry point exists.
|
|
107
|
-
// TODO_ESM: Make import failure an error once the `tools` entry point exists.
|
|
108
105
|
if (i18nPluginCreators === undefined) {
|
|
109
106
|
// Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
|
|
110
107
|
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
111
108
|
// changed to a direct dynamic import.
|
|
112
|
-
|
|
113
|
-
i18nPluginCreators = await (0, load_esm_1.loadEsmModule)('@angular/localize/tools');
|
|
114
|
-
}
|
|
115
|
-
catch { }
|
|
109
|
+
i18nPluginCreators = await (0, load_esm_1.loadEsmModule)('@angular/localize/tools');
|
|
116
110
|
}
|
|
117
111
|
customOptions.i18n = {
|
|
118
112
|
...i18n,
|
|
119
113
|
pluginCreators: i18nPluginCreators,
|
|
120
114
|
};
|
|
115
|
+
// Add translation files as dependencies of the file to support rebuilds
|
|
116
|
+
// Except for `@angular/core` which needs locale injection but has no translations
|
|
117
|
+
if (customOptions.i18n.translationFiles &&
|
|
118
|
+
!/[\\/]@angular[\\/]core/.test(this.resourcePath)) {
|
|
119
|
+
for (const file of customOptions.i18n.translationFiles) {
|
|
120
|
+
this.addDependency(file);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
121
123
|
shouldProcess = true;
|
|
122
124
|
}
|
|
123
125
|
if (optimize) {
|
|
@@ -199,7 +201,13 @@ exports.default = (0, babel_loader_1.custom)(() => {
|
|
|
199
201
|
// `@ampproject/remapping` source map objects but both are compatible with Webpack.
|
|
200
202
|
// This method for merging is used because it provides more accurate output
|
|
201
203
|
// and is faster while using less memory.
|
|
202
|
-
result.map =
|
|
204
|
+
result.map = {
|
|
205
|
+
// Convert the SourceMap back to simple plain object.
|
|
206
|
+
// This is needed because otherwise code-coverage will fail with `don't know how to turn this value into a node`
|
|
207
|
+
// Which is thrown by Babel if it is invoked again from `istanbul-lib-instrument`.
|
|
208
|
+
// https://github.com/babel/babel/blob/780aa48d2a34dc55f556843074b6aed45e7eabeb/packages/babel-types/src/converters/valueToNode.ts#L115-L130
|
|
209
|
+
...(0, remapping_1.default)([result.map, inputSourceMap], () => null),
|
|
210
|
+
};
|
|
203
211
|
}
|
|
204
212
|
return result;
|
|
205
213
|
},
|
|
@@ -155,8 +155,9 @@ function buildWebpackBrowser(options, context, transforms = {}) {
|
|
|
155
155
|
}
|
|
156
156
|
// Check for budget errors and display them to the user.
|
|
157
157
|
const budgets = options.budgets;
|
|
158
|
+
let budgetFailures;
|
|
158
159
|
if (budgets === null || budgets === void 0 ? void 0 : budgets.length) {
|
|
159
|
-
|
|
160
|
+
budgetFailures = [...(0, bundle_calculator_1.checkBudgets)(budgets, webpackStats)];
|
|
160
161
|
for (const { severity, message } of budgetFailures) {
|
|
161
162
|
switch (severity) {
|
|
162
163
|
case bundle_calculator_1.ThresholdSeverity.Warning:
|
|
@@ -250,7 +251,7 @@ function buildWebpackBrowser(options, context, transforms = {}) {
|
|
|
250
251
|
spinner.succeed('Service worker generation complete.');
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
|
-
(0, stats_1.webpackStatsLogger)(context.logger, webpackStats, config);
|
|
254
|
+
(0, stats_1.webpackStatsLogger)(context.logger, webpackStats, config, budgetFailures);
|
|
254
255
|
return { success: buildSuccess };
|
|
255
256
|
}
|
|
256
257
|
}), (0, operators_1.map)((event) => ({
|
|
@@ -37,10 +37,13 @@ const url = __importStar(require("url"));
|
|
|
37
37
|
const utils_1 = require("../../utils");
|
|
38
38
|
const check_port_1 = require("../../utils/check-port");
|
|
39
39
|
const color_1 = require("../../utils/color");
|
|
40
|
+
const i18n_options_1 = require("../../utils/i18n-options");
|
|
41
|
+
const load_translations_1 = require("../../utils/load-translations");
|
|
40
42
|
const normalize_cache_1 = require("../../utils/normalize-cache");
|
|
41
43
|
const package_chunk_sort_1 = require("../../utils/package-chunk-sort");
|
|
42
44
|
const version_1 = require("../../utils/version");
|
|
43
45
|
const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
46
|
+
const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
|
|
44
47
|
const configs_1 = require("../../webpack/configs");
|
|
45
48
|
const index_html_webpack_plugin_1 = require("../../webpack/plugins/index-html-webpack-plugin");
|
|
46
49
|
const stats_1 = require("../../webpack/utils/stats");
|
|
@@ -145,7 +148,7 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
145
148
|
if (i18n.inlineLocales.size > 1) {
|
|
146
149
|
throw new Error('The development server only supports localizing a single locale per build.');
|
|
147
150
|
}
|
|
148
|
-
await setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheOptions);
|
|
151
|
+
await setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheOptions, context);
|
|
149
152
|
}
|
|
150
153
|
if (transforms.webpackConfiguration) {
|
|
151
154
|
webpackConfig = await transforms.webpackConfiguration(webpackConfig);
|
|
@@ -220,7 +223,7 @@ function serveWebpackBrowser(options, context, transforms = {}) {
|
|
|
220
223
|
}));
|
|
221
224
|
}
|
|
222
225
|
exports.serveWebpackBrowser = serveWebpackBrowser;
|
|
223
|
-
async function setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheOptions) {
|
|
226
|
+
async function setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheOptions, context) {
|
|
224
227
|
var _a;
|
|
225
228
|
const localeDescription = i18n.locales[locale];
|
|
226
229
|
// Modify main entrypoint to include locale data
|
|
@@ -248,6 +251,7 @@ async function setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheO
|
|
|
248
251
|
locale,
|
|
249
252
|
missingTranslationBehavior,
|
|
250
253
|
translation: i18n.shouldInline ? translation : undefined,
|
|
254
|
+
translationFiles: localeDescription === null || localeDescription === void 0 ? void 0 : localeDescription.files.map((file) => path.resolve(context.workspaceRoot, file.path)),
|
|
251
255
|
};
|
|
252
256
|
const i18nRule = {
|
|
253
257
|
test: /\.[cm]?[tj]sx?$/,
|
|
@@ -276,5 +280,30 @@ async function setupLocalize(locale, i18n, browserOptions, webpackConfig, cacheO
|
|
|
276
280
|
webpackConfig.module.rules = rules;
|
|
277
281
|
}
|
|
278
282
|
rules.push(i18nRule);
|
|
283
|
+
// Add a plugin to reload translation files on rebuilds
|
|
284
|
+
const loader = await (0, load_translations_1.createTranslationLoader)();
|
|
285
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
286
|
+
webpackConfig.plugins.push({
|
|
287
|
+
apply: (compiler) => {
|
|
288
|
+
compiler.hooks.thisCompilation.tap('build-angular', (compilation) => {
|
|
289
|
+
if (i18n.shouldInline && i18nLoaderOptions.translation === undefined) {
|
|
290
|
+
// Reload translations
|
|
291
|
+
(0, i18n_options_1.loadTranslations)(locale, localeDescription, context.workspaceRoot, loader, {
|
|
292
|
+
warn(message) {
|
|
293
|
+
(0, webpack_diagnostics_1.addWarning)(compilation, message);
|
|
294
|
+
},
|
|
295
|
+
error(message) {
|
|
296
|
+
(0, webpack_diagnostics_1.addError)(compilation, message);
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
i18nLoaderOptions.translation = localeDescription.translation;
|
|
300
|
+
}
|
|
301
|
+
compilation.hooks.finishModules.tap('build-angular', () => {
|
|
302
|
+
// After loaders are finished, clear out the now unneeded translations
|
|
303
|
+
i18nLoaderOptions.translation = undefined;
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
});
|
|
279
308
|
}
|
|
280
309
|
exports.default = (0, architect_1.createBuilder)(serveWebpackBrowser);
|
|
@@ -29,6 +29,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
const nodePath = __importStar(require("path"));
|
|
30
30
|
const load_esm_1 = require("../../utils/load-esm");
|
|
31
31
|
function localizeExtractLoader(content, map) {
|
|
32
|
+
// This loader is not cacheable due to how message extraction works.
|
|
33
|
+
// Extracted messages are not part of webpack pipeline and hence they cannot be retrieved from cache.
|
|
34
|
+
// TODO: We should investigate in the future on making this deterministic and more cacheable.
|
|
35
|
+
this.cacheable(false);
|
|
32
36
|
const options = this.getOptions();
|
|
33
37
|
const callback = this.async();
|
|
34
38
|
extract(this, content, map, options).then(() => {
|
|
@@ -43,7 +47,6 @@ async function extract(loaderContext, content, map, options) {
|
|
|
43
47
|
// Try to load the `@angular/localize` message extractor.
|
|
44
48
|
// All the localize usages are setup to first try the ESM entry point then fallback to the deep imports.
|
|
45
49
|
// This provides interim compatibility while the framework is transitioned to bundled ESM packages.
|
|
46
|
-
// TODO_ESM: Remove all deep imports once `@angular/localize` is published with the `tools` entry point
|
|
47
50
|
let MessageExtractor;
|
|
48
51
|
try {
|
|
49
52
|
// Load ESM `@angular/localize/tools` using the TypeScript dynamic import workaround.
|
|
@@ -20,13 +20,12 @@ export declare enum ThresholdSeverity {
|
|
|
20
20
|
Warning = "warning",
|
|
21
21
|
Error = "error"
|
|
22
22
|
}
|
|
23
|
-
export
|
|
24
|
-
export declare function checkBudgets(budgets: Budget[], webpackStats: StatsCompilation): IterableIterator<{
|
|
25
|
-
severity: ThresholdSeverity;
|
|
26
|
-
message: string;
|
|
27
|
-
}>;
|
|
28
|
-
export declare function checkThresholds(thresholds: IterableIterator<Threshold>, size: number, label?: string): IterableIterator<{
|
|
23
|
+
export interface BudgetCalculatorResult {
|
|
29
24
|
severity: ThresholdSeverity;
|
|
30
25
|
message: string;
|
|
31
|
-
|
|
26
|
+
label?: string;
|
|
27
|
+
}
|
|
28
|
+
export declare function calculateThresholds(budget: Budget): IterableIterator<Threshold>;
|
|
29
|
+
export declare function checkBudgets(budgets: Budget[], webpackStats: StatsCompilation): IterableIterator<BudgetCalculatorResult>;
|
|
30
|
+
export declare function checkThresholds(thresholds: IterableIterator<Threshold>, size: number, label?: string): IterableIterator<BudgetCalculatorResult>;
|
|
32
31
|
export {};
|
|
@@ -143,7 +143,7 @@ class BundleCalculator extends Calculator {
|
|
|
143
143
|
.filter((chunk) => { var _a; return (_a = chunk === null || chunk === void 0 ? void 0 : chunk.names) === null || _a === void 0 ? void 0 : _a.includes(budgetName); })
|
|
144
144
|
.map((chunk) => this.calculateChunkSize(chunk))
|
|
145
145
|
.reduce((l, r) => l + r, 0);
|
|
146
|
-
return [{ size, label:
|
|
146
|
+
return [{ size, label: this.budget.name }];
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
/**
|
|
@@ -262,6 +262,7 @@ function* checkThresholds(thresholds, size, label) {
|
|
|
262
262
|
const sizeDifference = (0, stats_1.formatSize)(size - threshold.limit);
|
|
263
263
|
yield {
|
|
264
264
|
severity: threshold.severity,
|
|
265
|
+
label,
|
|
265
266
|
message: `${label} exceeded maximum budget. Budget ${(0, stats_1.formatSize)(threshold.limit)} was not met by ${sizeDifference} with a total of ${(0, stats_1.formatSize)(size)}.`,
|
|
266
267
|
};
|
|
267
268
|
break;
|
|
@@ -273,6 +274,7 @@ function* checkThresholds(thresholds, size, label) {
|
|
|
273
274
|
const sizeDifference = (0, stats_1.formatSize)(threshold.limit - size);
|
|
274
275
|
yield {
|
|
275
276
|
severity: threshold.severity,
|
|
277
|
+
label,
|
|
276
278
|
message: `${label} failed to meet minimum budget. Budget ${(0, stats_1.formatSize)(threshold.limit)} was not met by ${sizeDifference} with a total of ${(0, stats_1.formatSize)(size)}.`,
|
|
277
279
|
};
|
|
278
280
|
break;
|
|
@@ -8,6 +8,5 @@
|
|
|
8
8
|
export declare const allowMangle: boolean;
|
|
9
9
|
export declare const shouldBeautify: boolean;
|
|
10
10
|
export declare const allowMinify: boolean;
|
|
11
|
-
export declare const profilingEnabled: boolean;
|
|
12
11
|
export declare const maxWorkers: number;
|
|
13
12
|
export declare const cachingDisabled: boolean | null;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* found in the LICENSE file at https://angular.io/license
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.cachingDisabled = exports.maxWorkers = exports.
|
|
10
|
+
exports.cachingDisabled = exports.maxWorkers = exports.allowMinify = exports.shouldBeautify = exports.allowMangle = void 0;
|
|
11
11
|
const color_1 = require("./color");
|
|
12
12
|
function isDisabled(variable) {
|
|
13
13
|
return variable === '0' || variable.toLowerCase() === 'false';
|
|
@@ -57,9 +57,6 @@ exports.allowMangle = isPresent(mangleVariable)
|
|
|
57
57
|
: debugOptimize.mangle;
|
|
58
58
|
exports.shouldBeautify = debugOptimize.beautify;
|
|
59
59
|
exports.allowMinify = debugOptimize.minify;
|
|
60
|
-
// Build profiling
|
|
61
|
-
const profilingVariable = process.env['NG_BUILD_PROFILING'];
|
|
62
|
-
exports.profilingEnabled = isPresent(profilingVariable) && isEnabled(profilingVariable);
|
|
63
60
|
/**
|
|
64
61
|
* Some environments, like CircleCI which use Docker report a number of CPUs by the host and not the count of available.
|
|
65
62
|
* This cause `Error: Call retries were exceeded` errors when trying to use them.
|
|
@@ -9,19 +9,21 @@ import { BuilderContext } from '@angular-devkit/architect';
|
|
|
9
9
|
import { json } from '@angular-devkit/core';
|
|
10
10
|
import { Schema as BrowserBuilderSchema } from '../builders/browser/schema';
|
|
11
11
|
import { Schema as ServerBuilderSchema } from '../builders/server/schema';
|
|
12
|
+
import { TranslationLoader } from './load-translations';
|
|
13
|
+
export interface LocaleDescription {
|
|
14
|
+
files: {
|
|
15
|
+
path: string;
|
|
16
|
+
integrity?: string;
|
|
17
|
+
format?: string;
|
|
18
|
+
}[];
|
|
19
|
+
translation?: Record<string, unknown>;
|
|
20
|
+
dataPath?: string;
|
|
21
|
+
baseHref?: string;
|
|
22
|
+
}
|
|
12
23
|
export interface I18nOptions {
|
|
13
24
|
inlineLocales: Set<string>;
|
|
14
25
|
sourceLocale: string;
|
|
15
|
-
locales: Record<string,
|
|
16
|
-
files: {
|
|
17
|
-
path: string;
|
|
18
|
-
integrity?: string;
|
|
19
|
-
format?: string;
|
|
20
|
-
}[];
|
|
21
|
-
translation?: Record<string, unknown>;
|
|
22
|
-
dataPath?: string;
|
|
23
|
-
baseHref?: string;
|
|
24
|
-
}>;
|
|
26
|
+
locales: Record<string, LocaleDescription>;
|
|
25
27
|
flatOutput?: boolean;
|
|
26
28
|
readonly shouldInline: boolean;
|
|
27
29
|
hasDefinedSourceLocale?: boolean;
|
|
@@ -31,3 +33,7 @@ export declare function configureI18nBuild<T extends BrowserBuilderSchema | Serv
|
|
|
31
33
|
buildOptions: T;
|
|
32
34
|
i18n: I18nOptions;
|
|
33
35
|
}>;
|
|
36
|
+
export declare function loadTranslations(locale: string, desc: LocaleDescription, workspaceRoot: string, loader: TranslationLoader, logger: {
|
|
37
|
+
warn: (message: string) => void;
|
|
38
|
+
error: (message: string) => void;
|
|
39
|
+
}, usedFormats?: Set<string>): void;
|
|
@@ -10,7 +10,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
10
10
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
11
|
};
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.configureI18nBuild = exports.createI18nOptions = void 0;
|
|
13
|
+
exports.loadTranslations = exports.configureI18nBuild = exports.createI18nOptions = void 0;
|
|
14
14
|
const core_1 = require("@angular-devkit/core");
|
|
15
15
|
const fs_1 = __importDefault(require("fs"));
|
|
16
16
|
const module_1 = __importDefault(require("module"));
|
|
@@ -158,42 +158,18 @@ async function configureI18nBuild(context, options) {
|
|
|
158
158
|
if (!desc.files.length) {
|
|
159
159
|
continue;
|
|
160
160
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
if (loadResult.locale !== undefined && loadResult.locale !== locale) {
|
|
175
|
-
context.logger.warn(`WARNING [${file.path}]: File target locale ('${loadResult.locale}') does not match configured locale ('${locale}')`);
|
|
176
|
-
}
|
|
177
|
-
usedFormats.add(loadResult.format);
|
|
178
|
-
if (usedFormats.size > 1 && tsConfig.options.enableI18nLegacyMessageIdFormat !== false) {
|
|
179
|
-
// This limitation is only for legacy message id support (defaults to true as of 9.0)
|
|
180
|
-
throw new Error('Localization currently only supports using one type of translation file format for the entire application.');
|
|
181
|
-
}
|
|
182
|
-
file.format = loadResult.format;
|
|
183
|
-
file.integrity = loadResult.integrity;
|
|
184
|
-
if (desc.translation) {
|
|
185
|
-
// Merge translations
|
|
186
|
-
for (const [id, message] of Object.entries(loadResult.translations)) {
|
|
187
|
-
if (desc.translation[id] !== undefined) {
|
|
188
|
-
context.logger.warn(`WARNING [${file.path}]: Duplicate translations for message '${id}' when merging`);
|
|
189
|
-
}
|
|
190
|
-
desc.translation[id] = message;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
// First or only translation file
|
|
195
|
-
desc.translation = loadResult.translations;
|
|
196
|
-
}
|
|
161
|
+
loader !== null && loader !== void 0 ? loader : (loader = await (0, load_translations_1.createTranslationLoader)());
|
|
162
|
+
loadTranslations(locale, desc, context.workspaceRoot, loader, {
|
|
163
|
+
warn(message) {
|
|
164
|
+
context.logger.warn(message);
|
|
165
|
+
},
|
|
166
|
+
error(message) {
|
|
167
|
+
throw new Error(message);
|
|
168
|
+
},
|
|
169
|
+
}, usedFormats);
|
|
170
|
+
if (usedFormats.size > 1 && tsConfig.options.enableI18nLegacyMessageIdFormat !== false) {
|
|
171
|
+
// This limitation is only for legacy message id support (defaults to true as of 9.0)
|
|
172
|
+
throw new Error('Localization currently only supports using one type of translation file format for the entire application.');
|
|
197
173
|
}
|
|
198
174
|
}
|
|
199
175
|
// If inlining store the output in a temporary location to facilitate post-processing
|
|
@@ -225,3 +201,36 @@ function findLocaleDataPath(locale, resolver) {
|
|
|
225
201
|
return null;
|
|
226
202
|
}
|
|
227
203
|
}
|
|
204
|
+
function loadTranslations(locale, desc, workspaceRoot, loader, logger, usedFormats) {
|
|
205
|
+
for (const file of desc.files) {
|
|
206
|
+
const loadResult = loader(path_1.default.join(workspaceRoot, file.path));
|
|
207
|
+
for (const diagnostics of loadResult.diagnostics.messages) {
|
|
208
|
+
if (diagnostics.type === 'error') {
|
|
209
|
+
logger.error(`Error parsing translation file '${file.path}': ${diagnostics.message}`);
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
logger.warn(`WARNING [${file.path}]: ${diagnostics.message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (loadResult.locale !== undefined && loadResult.locale !== locale) {
|
|
216
|
+
logger.warn(`WARNING [${file.path}]: File target locale ('${loadResult.locale}') does not match configured locale ('${locale}')`);
|
|
217
|
+
}
|
|
218
|
+
usedFormats === null || usedFormats === void 0 ? void 0 : usedFormats.add(loadResult.format);
|
|
219
|
+
file.format = loadResult.format;
|
|
220
|
+
file.integrity = loadResult.integrity;
|
|
221
|
+
if (desc.translation) {
|
|
222
|
+
// Merge translations
|
|
223
|
+
for (const [id, message] of Object.entries(loadResult.translations)) {
|
|
224
|
+
if (desc.translation[id] !== undefined) {
|
|
225
|
+
logger.warn(`WARNING [${file.path}]: Duplicate translations for message '${id}' when merging`);
|
|
226
|
+
}
|
|
227
|
+
desc.translation[id] = message;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
// First or only translation file
|
|
232
|
+
desc.translation = loadResult.translations;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
exports.loadTranslations = loadTranslations;
|
|
@@ -27,4 +27,8 @@ export interface FileInfo {
|
|
|
27
27
|
name: string;
|
|
28
28
|
extension: string;
|
|
29
29
|
}
|
|
30
|
-
export declare function augmentIndexHtml(params: AugmentIndexHtmlOptions): Promise<
|
|
30
|
+
export declare function augmentIndexHtml(params: AugmentIndexHtmlOptions): Promise<{
|
|
31
|
+
content: string;
|
|
32
|
+
warnings: string[];
|
|
33
|
+
errors: string[];
|
|
34
|
+
}>;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.augmentIndexHtml = void 0;
|
|
11
11
|
const crypto_1 = require("crypto");
|
|
12
|
+
const load_esm_1 = require("../load-esm");
|
|
12
13
|
const html_rewriting_stream_1 = require("./html-rewriting-stream");
|
|
13
14
|
/*
|
|
14
15
|
* Helper function used by the IndexHtmlWebpackPlugin.
|
|
@@ -18,6 +19,8 @@ const html_rewriting_stream_1 = require("./html-rewriting-stream");
|
|
|
18
19
|
*/
|
|
19
20
|
async function augmentIndexHtml(params) {
|
|
20
21
|
const { loadOutputFile, files, entrypoints, sri, deployUrl = '', lang, baseHref, html } = params;
|
|
22
|
+
const warnings = [];
|
|
23
|
+
const errors = [];
|
|
21
24
|
let { crossOrigin = 'none' } = params;
|
|
22
25
|
if (sri && crossOrigin === 'none') {
|
|
23
26
|
crossOrigin = 'anonymous';
|
|
@@ -72,6 +75,7 @@ async function augmentIndexHtml(params) {
|
|
|
72
75
|
}
|
|
73
76
|
linkTags.push(`<link ${attrs.join(' ')}>`);
|
|
74
77
|
}
|
|
78
|
+
const dir = lang ? await getLanguageDirection(lang, warnings) : undefined;
|
|
75
79
|
const { rewriter, transformedContent } = await (0, html_rewriting_stream_1.htmlRewritingStream)(html);
|
|
76
80
|
const baseTagExists = html.includes('<base');
|
|
77
81
|
rewriter
|
|
@@ -82,6 +86,9 @@ async function augmentIndexHtml(params) {
|
|
|
82
86
|
if (isString(lang)) {
|
|
83
87
|
updateAttribute(tag, 'lang', lang);
|
|
84
88
|
}
|
|
89
|
+
if (dir) {
|
|
90
|
+
updateAttribute(tag, 'dir', dir);
|
|
91
|
+
}
|
|
85
92
|
break;
|
|
86
93
|
case 'head':
|
|
87
94
|
// Base href should be added before any link, meta tags
|
|
@@ -119,11 +126,14 @@ async function augmentIndexHtml(params) {
|
|
|
119
126
|
rewriter.emitEndTag(tag);
|
|
120
127
|
});
|
|
121
128
|
const content = await transformedContent;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
129
|
+
return {
|
|
130
|
+
content: linkTags.length || scriptTags.length
|
|
131
|
+
? // In case no body/head tags are not present (dotnet partial templates)
|
|
132
|
+
linkTags.join('') + scriptTags.join('') + content
|
|
133
|
+
: content,
|
|
134
|
+
warnings,
|
|
135
|
+
errors,
|
|
136
|
+
};
|
|
127
137
|
}
|
|
128
138
|
exports.augmentIndexHtml = augmentIndexHtml;
|
|
129
139
|
function generateSriAttributes(content) {
|
|
@@ -144,3 +154,26 @@ function updateAttribute(tag, name, value) {
|
|
|
144
154
|
function isString(value) {
|
|
145
155
|
return typeof value === 'string';
|
|
146
156
|
}
|
|
157
|
+
async function getLanguageDirection(locale, warnings) {
|
|
158
|
+
const dir = await getLanguageDirectionFromLocales(locale);
|
|
159
|
+
if (!dir) {
|
|
160
|
+
warnings.push(`Locale data for '${locale}' cannot be found. 'dir' attribute will not be set for this locale.`);
|
|
161
|
+
}
|
|
162
|
+
return dir;
|
|
163
|
+
}
|
|
164
|
+
async function getLanguageDirectionFromLocales(locale) {
|
|
165
|
+
try {
|
|
166
|
+
const localeData = (await (0, load_esm_1.loadEsmModule)(`@angular/common/locales/${locale}`)).default;
|
|
167
|
+
const dir = localeData[localeData.length - 2];
|
|
168
|
+
return isString(dir) ? dir : undefined;
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// In some cases certain locales might map to files which are named only with language id.
|
|
172
|
+
// Example: `en-US` -> `en`.
|
|
173
|
+
const [languageId] = locale.split('-', 1);
|
|
174
|
+
if (languageId !== locale) {
|
|
175
|
+
return getLanguageDirectionFromLocales(languageId);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
@@ -41,10 +41,7 @@ async function readTsconfig(tsconfigPath, workspaceRoot) {
|
|
|
41
41
|
// Load ESM `@angular/compiler-cli` using the TypeScript dynamic import workaround.
|
|
42
42
|
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
43
43
|
// changed to a direct dynamic import.
|
|
44
|
-
const
|
|
45
|
-
// If it is not ESM then the functions needed will be stored in the `default` property.
|
|
46
|
-
// TODO_ESM: This can be removed once `@angular/compiler-cli` is ESM only.
|
|
47
|
-
const { formatDiagnostics, readConfiguration } = (compilerCliModule.readConfiguration ? compilerCliModule : compilerCliModule.default);
|
|
44
|
+
const { formatDiagnostics, readConfiguration } = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli');
|
|
48
45
|
const configResult = readConfiguration(tsConfigFullPath);
|
|
49
46
|
if (configResult.errors && configResult.errors.length) {
|
|
50
47
|
throw new Error(formatDiagnostics(configResult.errors));
|
|
@@ -39,6 +39,7 @@ const webpack_subresource_integrity_1 = require("webpack-subresource-integrity")
|
|
|
39
39
|
const environment_options_1 = require("../../utils/environment-options");
|
|
40
40
|
const load_esm_1 = require("../../utils/load-esm");
|
|
41
41
|
const plugins_1 = require("../plugins");
|
|
42
|
+
const named_chunks_plugin_1 = require("../plugins/named-chunks-plugin");
|
|
42
43
|
const progress_plugin_1 = require("../plugins/progress-plugin");
|
|
43
44
|
const transfer_size_plugin_1 = require("../plugins/transfer-size-plugin");
|
|
44
45
|
const typescript_2 = require("../plugins/typescript");
|
|
@@ -46,7 +47,7 @@ const helpers_1 = require("../utils/helpers");
|
|
|
46
47
|
// eslint-disable-next-line max-lines-per-function
|
|
47
48
|
async function getCommonConfig(wco) {
|
|
48
49
|
var _a, _b;
|
|
49
|
-
const { root, projectRoot, buildOptions, tsConfig, projectName, sourceRoot, tsConfigPath } = wco;
|
|
50
|
+
const { root, projectRoot, buildOptions, tsConfig, projectName, sourceRoot, tsConfigPath, scriptTarget, } = wco;
|
|
50
51
|
const { cache, codeCoverage, crossOrigin = 'none', platform = 'browser', aot = true, codeCoverageExclude = [], main, polyfills, sourceMap: { styles: stylesSourceMap, scripts: scriptsSourceMap, vendor: vendorSourceMap, hidden: hiddenSourceMap, }, optimization: { styles: stylesOptimization, scripts: scriptsOptimization }, commonChunk, vendorChunk, subresourceIntegrity, verbose, poll, webWorkerTsConfig, externalDependencies = [], allowedCommonJsDependencies, bundleDependencies, } = buildOptions;
|
|
51
52
|
const isPlatformServer = buildOptions.platform === 'server';
|
|
52
53
|
const extraPlugins = [];
|
|
@@ -55,10 +56,7 @@ async function getCommonConfig(wco) {
|
|
|
55
56
|
// Load ESM `@angular/compiler-cli` using the TypeScript dynamic import workaround.
|
|
56
57
|
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
57
58
|
// changed to a direct dynamic import.
|
|
58
|
-
const
|
|
59
|
-
// If it is not ESM then the values needed will be stored in the `default` property.
|
|
60
|
-
// TODO_ESM: This can be removed once `@angular/compiler-cli` is ESM only.
|
|
61
|
-
const { GLOBAL_DEFS_FOR_TERSER, GLOBAL_DEFS_FOR_TERSER_WITH_AOT, VERSION: NG_VERSION, } = (compilerCliModule.GLOBAL_DEFS_FOR_TERSER ? compilerCliModule : compilerCliModule.default);
|
|
59
|
+
const { GLOBAL_DEFS_FOR_TERSER, GLOBAL_DEFS_FOR_TERSER_WITH_AOT, VERSION: NG_VERSION, } = await (0, load_esm_1.loadEsmModule)('@angular/compiler-cli');
|
|
62
60
|
// determine hashing format
|
|
63
61
|
const hashFormat = (0, helpers_1.getOutputHashFormat)(buildOptions.outputHashing || 'none');
|
|
64
62
|
if (buildOptions.progress) {
|
|
@@ -92,11 +90,6 @@ async function getCommonConfig(wco) {
|
|
|
92
90
|
}
|
|
93
91
|
}
|
|
94
92
|
}
|
|
95
|
-
if (environment_options_1.profilingEnabled) {
|
|
96
|
-
extraPlugins.push(new webpack_2.debug.ProfilingPlugin({
|
|
97
|
-
outputPath: path.resolve(root, 'chrome-profiler-events.json'),
|
|
98
|
-
}));
|
|
99
|
-
}
|
|
100
93
|
if (allowedCommonJsDependencies) {
|
|
101
94
|
// When this is not defined it means the builder doesn't support showing common js usages.
|
|
102
95
|
// When it does it will be an array.
|
|
@@ -189,8 +182,10 @@ async function getCommonConfig(wco) {
|
|
|
189
182
|
}
|
|
190
183
|
if (main || polyfills) {
|
|
191
184
|
extraRules.push({
|
|
192
|
-
test: /\.[cm]?[tj]sx?$/,
|
|
185
|
+
test: tsConfig.options.allowJs ? /\.[cm]?[tj]sx?$/ : /\.[cm]?tsx?$/,
|
|
193
186
|
loader: webpack_1.AngularWebpackLoaderPath,
|
|
187
|
+
// The below are known paths that are not part of the TypeScript compilation even when allowJs is enabled.
|
|
188
|
+
exclude: [/[/\\](?:css-loader|mini-css-extract-plugin|webpack-dev-server|webpack)[/\\]/],
|
|
194
189
|
});
|
|
195
190
|
extraPlugins.push((0, typescript_2.createIvyPlugin)(wco, aot, tsConfigPath));
|
|
196
191
|
}
|
|
@@ -202,7 +197,7 @@ async function getCommonConfig(wco) {
|
|
|
202
197
|
extraMinimizers.push(new plugins_1.JavaScriptOptimizerPlugin({
|
|
203
198
|
define: buildOptions.aot ? GLOBAL_DEFS_FOR_TERSER_WITH_AOT : GLOBAL_DEFS_FOR_TERSER,
|
|
204
199
|
sourcemap: scriptsSourceMap,
|
|
205
|
-
target:
|
|
200
|
+
target: scriptTarget,
|
|
206
201
|
keepNames: !environment_options_1.allowMangle || isPlatformServer,
|
|
207
202
|
removeLicenses: buildOptions.extractLicenses,
|
|
208
203
|
advanced: buildOptions.buildOptimizer,
|
|
@@ -227,7 +222,7 @@ async function getCommonConfig(wco) {
|
|
|
227
222
|
devtool: false,
|
|
228
223
|
target: [
|
|
229
224
|
isPlatformServer ? 'node' : 'web',
|
|
230
|
-
|
|
225
|
+
scriptTarget === typescript_1.ScriptTarget.ES5 ? 'es5' : 'es2015',
|
|
231
226
|
],
|
|
232
227
|
profile: buildOptions.statsJson,
|
|
233
228
|
resolve: {
|
|
@@ -235,10 +230,7 @@ async function getCommonConfig(wco) {
|
|
|
235
230
|
extensions: ['.ts', '.tsx', '.mjs', '.js'],
|
|
236
231
|
symlinks: !buildOptions.preserveSymlinks,
|
|
237
232
|
modules: [tsConfig.options.baseUrl || projectRoot, 'node_modules'],
|
|
238
|
-
|
|
239
|
-
? ['es2015', 'module', 'main']
|
|
240
|
-
: ['es2020', 'es2015', 'browser', 'module', 'main'],
|
|
241
|
-
conditionNames: isPlatformServer ? ['es2015', '...'] : ['es2020', 'es2015', '...'],
|
|
233
|
+
...(0, helpers_1.getMainFieldsAndConditionNames)(scriptTarget, isPlatformServer),
|
|
242
234
|
},
|
|
243
235
|
resolveLoader: {
|
|
244
236
|
symlinks: !buildOptions.preserveSymlinks,
|
|
@@ -262,7 +254,7 @@ async function getCommonConfig(wco) {
|
|
|
262
254
|
watch: buildOptions.watch,
|
|
263
255
|
watchOptions: {
|
|
264
256
|
poll,
|
|
265
|
-
ignored: poll === undefined ? undefined : 'node_modules/**',
|
|
257
|
+
ignored: poll === undefined ? undefined : '**/node_modules/**',
|
|
266
258
|
},
|
|
267
259
|
performance: {
|
|
268
260
|
hints: false,
|
|
@@ -288,6 +280,12 @@ async function getCommonConfig(wco) {
|
|
|
288
280
|
}
|
|
289
281
|
: undefined,
|
|
290
282
|
rules: [
|
|
283
|
+
{
|
|
284
|
+
test: /\.?(svg|html)$/,
|
|
285
|
+
// Only process HTML and SVG which are known Angular component resources.
|
|
286
|
+
resourceQuery: /\?ngResource/,
|
|
287
|
+
type: 'asset/source',
|
|
288
|
+
},
|
|
291
289
|
{
|
|
292
290
|
// Mark files inside `rxjs/add` as containing side effects.
|
|
293
291
|
// If this is fixed upstream and the fixed version becomes the minimum
|
|
@@ -305,7 +303,7 @@ async function getCommonConfig(wco) {
|
|
|
305
303
|
loader: require.resolve('../../babel/webpack-loader'),
|
|
306
304
|
options: {
|
|
307
305
|
cacheDirectory: (cache.enabled && path.join(cache.path, 'babel-webpack')) || false,
|
|
308
|
-
scriptTarget
|
|
306
|
+
scriptTarget,
|
|
309
307
|
aot: buildOptions.aot,
|
|
310
308
|
optimize: buildOptions.buildOptimizer,
|
|
311
309
|
instrumentCode: codeCoverage
|
|
@@ -362,7 +360,7 @@ async function getCommonConfig(wco) {
|
|
|
362
360
|
},
|
|
363
361
|
},
|
|
364
362
|
},
|
|
365
|
-
plugins: [new plugins_1.DedupeModuleResolvePlugin({ verbose }), ...extraPlugins],
|
|
363
|
+
plugins: [new named_chunks_plugin_1.NamedChunksPlugin(), new plugins_1.DedupeModuleResolvePlugin({ verbose }), ...extraPlugins],
|
|
366
364
|
node: false,
|
|
367
365
|
};
|
|
368
366
|
}
|
|
@@ -30,7 +30,7 @@ exports.buildServePath = exports.getDevServerConfig = void 0;
|
|
|
30
30
|
const core_1 = require("@angular-devkit/core");
|
|
31
31
|
const fs_1 = require("fs");
|
|
32
32
|
const path_1 = require("path");
|
|
33
|
-
const
|
|
33
|
+
const url_1 = require("url");
|
|
34
34
|
const load_esm_1 = require("../../utils/load-esm");
|
|
35
35
|
const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
36
36
|
const hmr_loader_1 = require("../plugins/hmr/hmr-loader");
|
|
@@ -78,7 +78,7 @@ async function getDevServerConfig(wco) {
|
|
|
78
78
|
rewrites: [
|
|
79
79
|
{
|
|
80
80
|
from: new RegExp(`^(?!${servePath})/.*`),
|
|
81
|
-
to: (context) =>
|
|
81
|
+
to: (context) => context.parsedUrl.href,
|
|
82
82
|
},
|
|
83
83
|
],
|
|
84
84
|
},
|
|
@@ -186,7 +186,7 @@ async function addProxyConfig(root, proxyConfig) {
|
|
|
186
186
|
// Load the ESM configuration file using the TypeScript dynamic import workaround.
|
|
187
187
|
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
188
188
|
// changed to a direct dynamic import.
|
|
189
|
-
return (await (0, load_esm_1.loadEsmModule)(
|
|
189
|
+
return (await (0, load_esm_1.loadEsmModule)((0, url_1.pathToFileURL)(proxyPath))).default;
|
|
190
190
|
case '.cjs':
|
|
191
191
|
return require(proxyPath);
|
|
192
192
|
default:
|
|
@@ -200,7 +200,7 @@ async function addProxyConfig(root, proxyConfig) {
|
|
|
200
200
|
// Load the ESM configuration file using the TypeScript dynamic import workaround.
|
|
201
201
|
// Once TypeScript provides support for keeping the dynamic import this workaround can be
|
|
202
202
|
// changed to a direct dynamic import.
|
|
203
|
-
return (await (0, load_esm_1.loadEsmModule)(
|
|
203
|
+
return (await (0, load_esm_1.loadEsmModule)((0, url_1.pathToFileURL)(proxyPath))).default;
|
|
204
204
|
}
|
|
205
205
|
throw e;
|
|
206
206
|
}
|
|
@@ -274,10 +274,8 @@ function getAllowedHostsConfig(options) {
|
|
|
274
274
|
function getPublicHostOptions(options, webSocketPath) {
|
|
275
275
|
let publicHost = options.publicHost;
|
|
276
276
|
if (publicHost) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
publicHost = url.parse(publicHost).host;
|
|
277
|
+
const hostWithProtocol = !/^\w+:\/\//.test(publicHost) ? `https://${publicHost}` : publicHost;
|
|
278
|
+
publicHost = new url_1.URL(hostWithProtocol).host;
|
|
281
279
|
}
|
|
282
280
|
return `auto://${publicHost || '0.0.0.0:0'}${webSocketPath}`;
|
|
283
281
|
}
|
|
@@ -91,14 +91,16 @@ function getStylesConfig(wco) {
|
|
|
91
91
|
wco.logger.warn('Stylus usage is deprecated and will be removed in a future major version. ' +
|
|
92
92
|
'To opt-out of the deprecated behaviour, please migrate to another stylesheet language.');
|
|
93
93
|
}
|
|
94
|
-
const sassImplementation =
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
compiler
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
const sassImplementation = getSassImplementation();
|
|
95
|
+
if (sassImplementation instanceof sass_service_1.SassWorkerImplementation) {
|
|
96
|
+
extraPlugins.push({
|
|
97
|
+
apply(compiler) {
|
|
98
|
+
compiler.hooks.shutdown.tap('sass-worker', () => {
|
|
99
|
+
sassImplementation === null || sassImplementation === void 0 ? void 0 : sassImplementation.close();
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
102
104
|
const assetNameTemplate = (0, helpers_1.assetNameTemplateFactory)(hashFormat);
|
|
103
105
|
const extraPostcssPlugins = [];
|
|
104
106
|
// Attempt to setup Tailwind CSS
|
|
@@ -340,14 +342,14 @@ function getStylesConfig(wco) {
|
|
|
340
342
|
oneOf: [
|
|
341
343
|
// Component styles are all styles except defined global styles
|
|
342
344
|
{
|
|
343
|
-
exclude: globalStylePaths,
|
|
344
345
|
use: componentStyleLoaders,
|
|
346
|
+
resourceQuery: /\?ngResource/,
|
|
345
347
|
type: 'asset/source',
|
|
346
348
|
},
|
|
347
349
|
// Global styles are only defined global styles
|
|
348
350
|
{
|
|
349
|
-
include: globalStylePaths,
|
|
350
351
|
use: globalStyleLoaders,
|
|
352
|
+
resourceQuery: { not: [/\?ngResource/] },
|
|
351
353
|
},
|
|
352
354
|
],
|
|
353
355
|
},
|
|
@@ -368,3 +370,12 @@ function getStylesConfig(wco) {
|
|
|
368
370
|
};
|
|
369
371
|
}
|
|
370
372
|
exports.getStylesConfig = getStylesConfig;
|
|
373
|
+
function getSassImplementation() {
|
|
374
|
+
const { webcontainer } = process.versions;
|
|
375
|
+
// When `webcontainer` is a truthy it means that we are running in a StackBlitz webcontainer.
|
|
376
|
+
// `SassWorkerImplementation` uses `receiveMessageOnPort` Node.js `worker_thread` API to ensure sync behavior which is ~2x faster.
|
|
377
|
+
// However, it is non trivial to support this in a webcontainer and while slower we choose to use `dart-sass`
|
|
378
|
+
// which in Webpack uses the slower async path.
|
|
379
|
+
// We should periodically check with StackBlitz folks (Mark Whitfeld / Dominic Elm) to determine if this workaround is still needed.
|
|
380
|
+
return webcontainer ? require('sass') : new sass_service_1.SassWorkerImplementation();
|
|
381
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { Compiler } from 'webpack';
|
|
9
|
+
/**
|
|
10
|
+
* Webpack will not populate the chunk `name` property unless `webpackChunkName` magic comment is used.
|
|
11
|
+
* This however will also effect the filename which is not desired when using `deterministic` chunkIds.
|
|
12
|
+
* This plugin will populate the chunk `name` which is mainly used so that users can set bundle budgets on lazy chunks.
|
|
13
|
+
*/
|
|
14
|
+
export declare class NamedChunksPlugin {
|
|
15
|
+
apply(compiler: Compiler): void;
|
|
16
|
+
private generateName;
|
|
17
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright Google LLC All Rights Reserved.
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://angular.io/license
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.NamedChunksPlugin = void 0;
|
|
11
|
+
const webpack_1 = require("webpack");
|
|
12
|
+
// `ImportDependency` is not part of Webpack's depenencies typings.
|
|
13
|
+
const ImportDependency = require('webpack/lib/dependencies/ImportDependency');
|
|
14
|
+
const PLUGIN_NAME = 'named-chunks-plugin';
|
|
15
|
+
/**
|
|
16
|
+
* Webpack will not populate the chunk `name` property unless `webpackChunkName` magic comment is used.
|
|
17
|
+
* This however will also effect the filename which is not desired when using `deterministic` chunkIds.
|
|
18
|
+
* This plugin will populate the chunk `name` which is mainly used so that users can set bundle budgets on lazy chunks.
|
|
19
|
+
*/
|
|
20
|
+
class NamedChunksPlugin {
|
|
21
|
+
apply(compiler) {
|
|
22
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
23
|
+
compilation.hooks.chunkAsset.tap(PLUGIN_NAME, (chunk) => {
|
|
24
|
+
if (chunk.name) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const name = this.generateName(chunk);
|
|
28
|
+
if (name) {
|
|
29
|
+
chunk.name = name;
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
generateName(chunk) {
|
|
35
|
+
for (const group of chunk.groupsIterable) {
|
|
36
|
+
const [block] = group.getBlocks();
|
|
37
|
+
if (!(block instanceof webpack_1.AsyncDependenciesBlock)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
for (const dependency of block.dependencies) {
|
|
41
|
+
if (dependency instanceof ImportDependency) {
|
|
42
|
+
return webpack_1.Template.toPath(dependency.request);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.NamedChunksPlugin = NamedChunksPlugin;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import type { ObjectPattern } from 'copy-webpack-plugin';
|
|
9
|
+
import { ScriptTarget } from 'typescript';
|
|
9
10
|
import type { Configuration, WebpackOptionsNormalized } from 'webpack';
|
|
10
11
|
import { AssetPatternClass, ExtraEntryPoint, ExtraEntryPointClass } from '../../builders/browser/schema';
|
|
11
12
|
import { WebpackConfigOptions } from '../../utils/build-options';
|
|
@@ -30,4 +31,5 @@ export declare function assetPatterns(root: string, assets: AssetPatternClass[])
|
|
|
30
31
|
export declare function externalizePackages(context: string, request: string | undefined, callback: (error?: Error, result?: string) => void): void;
|
|
31
32
|
declare type WebpackStatsOptions = Exclude<Configuration['stats'], string | boolean>;
|
|
32
33
|
export declare function getStatsOptions(verbose?: boolean): WebpackStatsOptions;
|
|
34
|
+
export declare function getMainFieldsAndConditionNames(target: ScriptTarget, platformServer: boolean): Pick<WebpackOptionsNormalized['resolve'], 'mainFields' | 'conditionNames'>;
|
|
33
35
|
export {};
|
|
@@ -29,11 +29,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
29
29
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
30
30
|
};
|
|
31
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
exports.getStatsOptions = exports.externalizePackages = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
|
|
32
|
+
exports.getMainFieldsAndConditionNames = exports.getStatsOptions = exports.externalizePackages = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
|
|
33
33
|
const crypto_1 = require("crypto");
|
|
34
34
|
const fs_1 = require("fs");
|
|
35
35
|
const glob_1 = __importDefault(require("glob"));
|
|
36
36
|
const path = __importStar(require("path"));
|
|
37
|
+
const typescript_1 = require("typescript");
|
|
37
38
|
function getOutputHashFormat(option, length = 20) {
|
|
38
39
|
const hashFormats = {
|
|
39
40
|
none: { chunk: '', extract: '', file: '', script: '' },
|
|
@@ -265,3 +266,18 @@ function getStatsOptions(verbose = false) {
|
|
|
265
266
|
: webpackOutputOptions;
|
|
266
267
|
}
|
|
267
268
|
exports.getStatsOptions = getStatsOptions;
|
|
269
|
+
function getMainFieldsAndConditionNames(target, platformServer) {
|
|
270
|
+
const mainFields = platformServer
|
|
271
|
+
? ['es2015', 'module', 'main']
|
|
272
|
+
: ['es2015', 'browser', 'module', 'main'];
|
|
273
|
+
const conditionNames = ['es2015', '...'];
|
|
274
|
+
if (target >= typescript_1.ScriptTarget.ES2020) {
|
|
275
|
+
mainFields.unshift('es2020');
|
|
276
|
+
conditionNames.unshift('es2020');
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
mainFields,
|
|
280
|
+
conditionNames,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
exports.getMainFieldsAndConditionNames = getMainFieldsAndConditionNames;
|
|
@@ -9,6 +9,7 @@ import { WebpackLoggingCallback } from '@angular-devkit/build-webpack';
|
|
|
9
9
|
import { logging } from '@angular-devkit/core';
|
|
10
10
|
import { Configuration, StatsCompilation } from 'webpack';
|
|
11
11
|
import { Schema as BrowserBuilderOptions } from '../../builders/browser/schema';
|
|
12
|
+
import { BudgetCalculatorResult } from '../../utils/bundle-calculator';
|
|
12
13
|
export declare function formatSize(size: number): string;
|
|
13
14
|
export declare type BundleStatsData = [
|
|
14
15
|
files: string,
|
|
@@ -33,4 +34,4 @@ export declare function statsErrorsToString(json: StatsCompilation, statsConfig:
|
|
|
33
34
|
export declare function statsHasErrors(json: StatsCompilation): boolean;
|
|
34
35
|
export declare function statsHasWarnings(json: StatsCompilation): boolean;
|
|
35
36
|
export declare function createWebpackLoggingCallback(options: BrowserBuilderOptions, logger: logging.LoggerApi): WebpackLoggingCallback;
|
|
36
|
-
export declare function webpackStatsLogger(logger: logging.LoggerApi, json: StatsCompilation, config: Configuration,
|
|
37
|
+
export declare function webpackStatsLogger(logger: logging.LoggerApi, json: StatsCompilation, config: Configuration, budgetFailures?: BudgetCalculatorResult[]): void;
|
|
@@ -61,30 +61,59 @@ function generateBundleStats(info) {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
exports.generateBundleStats = generateBundleStats;
|
|
64
|
-
function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize) {
|
|
64
|
+
function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures) {
|
|
65
65
|
const g = (x) => (colors ? color_1.colors.greenBright(x) : x);
|
|
66
66
|
const c = (x) => (colors ? color_1.colors.cyanBright(x) : x);
|
|
67
|
+
const r = (x) => (colors ? color_1.colors.redBright(x) : x);
|
|
68
|
+
const y = (x) => (colors ? color_1.colors.yellowBright(x) : x);
|
|
67
69
|
const bold = (x) => (colors ? color_1.colors.bold(x) : x);
|
|
68
70
|
const dim = (x) => (colors ? color_1.colors.dim(x) : x);
|
|
71
|
+
const getSizeColor = (name, file, defaultColor = c) => {
|
|
72
|
+
const severity = budgets.get(name) || (file && budgets.get(file));
|
|
73
|
+
switch (severity) {
|
|
74
|
+
case 'warning':
|
|
75
|
+
return y;
|
|
76
|
+
case 'error':
|
|
77
|
+
return r;
|
|
78
|
+
default:
|
|
79
|
+
return defaultColor;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
69
82
|
const changedEntryChunksStats = [];
|
|
70
83
|
const changedLazyChunksStats = [];
|
|
71
84
|
let initialTotalRawSize = 0;
|
|
72
85
|
let initialTotalEstimatedTransferSize;
|
|
86
|
+
const budgets = new Map();
|
|
87
|
+
if (budgetFailures) {
|
|
88
|
+
for (const { label, severity } of budgetFailures) {
|
|
89
|
+
// In some cases a file can have multiple budget failures.
|
|
90
|
+
// Favor error.
|
|
91
|
+
if (label && (!budgets.has(label) || budgets.get(label) === 'warning')) {
|
|
92
|
+
budgets.set(label, severity);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
73
96
|
for (const { initial, stats } of data) {
|
|
74
97
|
const [files, names, rawSize, estimatedTransferSize] = stats;
|
|
98
|
+
const getRawSizeColor = getSizeColor(names, files);
|
|
75
99
|
let data;
|
|
76
100
|
if (showEstimatedTransferSize) {
|
|
77
101
|
data = [
|
|
78
102
|
g(files),
|
|
79
103
|
names,
|
|
80
|
-
|
|
104
|
+
getRawSizeColor(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize),
|
|
81
105
|
c(typeof estimatedTransferSize === 'number'
|
|
82
106
|
? formatSize(estimatedTransferSize)
|
|
83
107
|
: estimatedTransferSize),
|
|
84
108
|
];
|
|
85
109
|
}
|
|
86
110
|
else {
|
|
87
|
-
data = [
|
|
111
|
+
data = [
|
|
112
|
+
g(files),
|
|
113
|
+
names,
|
|
114
|
+
getRawSizeColor(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize),
|
|
115
|
+
'',
|
|
116
|
+
];
|
|
88
117
|
}
|
|
89
118
|
if (initial) {
|
|
90
119
|
changedEntryChunksStats.push(data);
|
|
@@ -114,7 +143,12 @@ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTrans
|
|
|
114
143
|
bundleInfo.push(['Initial Chunk Files', ...baseTitles].map(bold), ...changedEntryChunksStats);
|
|
115
144
|
if (showTotalSize) {
|
|
116
145
|
bundleInfo.push([]);
|
|
117
|
-
const
|
|
146
|
+
const initialSizeTotalColor = getSizeColor('bundle initial', undefined, (x) => x);
|
|
147
|
+
const totalSizeElements = [
|
|
148
|
+
' ',
|
|
149
|
+
'Initial Total',
|
|
150
|
+
initialSizeTotalColor(formatSize(initialTotalRawSize)),
|
|
151
|
+
];
|
|
118
152
|
if (showEstimatedTransferSize) {
|
|
119
153
|
totalSizeElements.push(typeof initialTotalEstimatedTransferSize === 'number'
|
|
120
154
|
? formatSize(initialTotalEstimatedTransferSize)
|
|
@@ -147,47 +181,45 @@ function generateBuildStats(hash, time, colors) {
|
|
|
147
181
|
const runsCache = new Set();
|
|
148
182
|
function statsToString(json,
|
|
149
183
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
150
|
-
statsConfig,
|
|
184
|
+
statsConfig, budgetFailures) {
|
|
151
185
|
var _a, _b;
|
|
152
186
|
if (!((_a = json.chunks) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
153
187
|
return '';
|
|
154
188
|
}
|
|
155
189
|
const colors = statsConfig.colors;
|
|
156
190
|
const rs = (x) => (colors ? color_1.colors.reset(x) : x);
|
|
157
|
-
const changedChunksStats =
|
|
191
|
+
const changedChunksStats = [];
|
|
158
192
|
let unchangedChunkNumber = 0;
|
|
159
193
|
let hasEstimatedTransferSizes = false;
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
hasEstimatedTransferSizes = true;
|
|
181
|
-
}
|
|
182
|
-
estimatedTransferSize += asset.info.estimatedTransferSize;
|
|
194
|
+
const isFirstRun = !runsCache.has(json.outputPath || '');
|
|
195
|
+
for (const chunk of json.chunks) {
|
|
196
|
+
// During first build we want to display unchanged chunks
|
|
197
|
+
// but unchanged cached chunks are always marked as not rendered.
|
|
198
|
+
if (!isFirstRun && !chunk.rendered) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const assets = (_b = json.assets) === null || _b === void 0 ? void 0 : _b.filter((asset) => { var _a; return (_a = chunk.files) === null || _a === void 0 ? void 0 : _a.includes(asset.name); });
|
|
202
|
+
let rawSize = 0;
|
|
203
|
+
let estimatedTransferSize;
|
|
204
|
+
if (assets) {
|
|
205
|
+
for (const asset of assets) {
|
|
206
|
+
if (asset.name.endsWith('.map')) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
rawSize += asset.size;
|
|
210
|
+
if (typeof asset.info.estimatedTransferSize === 'number') {
|
|
211
|
+
if (estimatedTransferSize === undefined) {
|
|
212
|
+
estimatedTransferSize = 0;
|
|
213
|
+
hasEstimatedTransferSizes = true;
|
|
183
214
|
}
|
|
215
|
+
estimatedTransferSize += asset.info.estimatedTransferSize;
|
|
184
216
|
}
|
|
185
217
|
}
|
|
186
|
-
changedChunksStats.push(generateBundleStats({ ...chunk, rawSize, estimatedTransferSize }));
|
|
187
218
|
}
|
|
188
|
-
|
|
189
|
-
runsCache.add(json.outputPath || '');
|
|
219
|
+
changedChunksStats.push(generateBundleStats({ ...chunk, rawSize, estimatedTransferSize }));
|
|
190
220
|
}
|
|
221
|
+
unchangedChunkNumber = json.chunks.length - changedChunksStats.length;
|
|
222
|
+
runsCache.add(json.outputPath || '');
|
|
191
223
|
// Sort chunks by size in descending order
|
|
192
224
|
changedChunksStats.sort((a, b) => {
|
|
193
225
|
if (a.stats[2] > b.stats[2]) {
|
|
@@ -198,7 +230,7 @@ statsConfig, bundleState) {
|
|
|
198
230
|
}
|
|
199
231
|
return 0;
|
|
200
232
|
});
|
|
201
|
-
const statsTable = generateBuildStatsTable(changedChunksStats, colors, unchangedChunkNumber === 0, hasEstimatedTransferSizes);
|
|
233
|
+
const statsTable = generateBuildStatsTable(changedChunksStats, colors, unchangedChunkNumber === 0, hasEstimatedTransferSizes, budgetFailures);
|
|
202
234
|
// In some cases we do things outside of webpack context
|
|
203
235
|
// Such us index generation, service worker augmentation etc...
|
|
204
236
|
// This will correct the time and include these.
|
|
@@ -320,8 +352,8 @@ function createWebpackLoggingCallback(options, logger) {
|
|
|
320
352
|
};
|
|
321
353
|
}
|
|
322
354
|
exports.createWebpackLoggingCallback = createWebpackLoggingCallback;
|
|
323
|
-
function webpackStatsLogger(logger, json, config,
|
|
324
|
-
logger.info(statsToString(json, config.stats,
|
|
355
|
+
function webpackStatsLogger(logger, json, config, budgetFailures) {
|
|
356
|
+
logger.info(statsToString(json, config.stats, budgetFailures));
|
|
325
357
|
if (statsHasWarnings(json)) {
|
|
326
358
|
logger.warn(statsWarningsToString(json, config.stats));
|
|
327
359
|
}
|