@angular-devkit/build-angular 15.0.0-next.3 → 15.0.0-next.5

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.
Files changed (53) hide show
  1. package/package.json +19 -18
  2. package/src/builders/app-shell/index.js +39 -40
  3. package/src/builders/app-shell/render-worker.d.ts +36 -0
  4. package/src/builders/app-shell/render-worker.js +82 -0
  5. package/src/builders/browser/index.d.ts +2 -0
  6. package/src/builders/browser/index.js +38 -19
  7. package/src/builders/browser/schema.json +2 -2
  8. package/src/builders/browser-esbuild/compiler-plugin.d.ts +10 -2
  9. package/src/builders/browser-esbuild/compiler-plugin.js +211 -115
  10. package/src/builders/browser-esbuild/esbuild.d.ts +4 -3
  11. package/src/builders/browser-esbuild/esbuild.js +12 -6
  12. package/src/builders/browser-esbuild/experimental-warnings.js +0 -3
  13. package/src/builders/browser-esbuild/index.d.ts +3 -3
  14. package/src/builders/browser-esbuild/index.js +145 -87
  15. package/src/builders/browser-esbuild/options.d.ts +26 -4
  16. package/src/builders/browser-esbuild/options.js +56 -5
  17. package/src/builders/browser-esbuild/profiling.d.ts +11 -0
  18. package/src/builders/browser-esbuild/profiling.js +64 -0
  19. package/src/builders/browser-esbuild/sass-plugin.js +11 -5
  20. package/src/builders/browser-esbuild/schema.json +2 -2
  21. package/src/builders/browser-esbuild/watcher.d.ts +23 -0
  22. package/src/builders/browser-esbuild/watcher.js +93 -0
  23. package/src/builders/dev-server/index.d.ts +2 -0
  24. package/src/builders/dev-server/index.js +10 -7
  25. package/src/builders/karma/find-tests-plugin.js +1 -0
  26. package/src/builders/karma/index.d.ts +1 -1
  27. package/src/builders/karma/index.js +50 -9
  28. package/src/builders/karma/schema.d.ts +1 -1
  29. package/src/builders/karma/schema.json +1 -1
  30. package/src/builders/server/schema.json +1 -1
  31. package/src/utils/environment-options.d.ts +1 -0
  32. package/src/utils/environment-options.js +3 -1
  33. package/src/utils/process-bundle.js +1 -1
  34. package/src/utils/service-worker.d.ts +3 -0
  35. package/src/utils/service-worker.js +29 -2
  36. package/src/webpack/configs/common.js +31 -7
  37. package/src/webpack/configs/index.d.ts +0 -1
  38. package/src/webpack/configs/index.js +0 -1
  39. package/src/webpack/configs/styles.d.ts +1 -7
  40. package/src/webpack/configs/styles.js +70 -60
  41. package/src/webpack/plugins/occurrences-plugin.d.ts +18 -0
  42. package/src/webpack/plugins/occurrences-plugin.js +79 -0
  43. package/src/webpack/plugins/scripts-webpack-plugin.js +24 -5
  44. package/src/webpack/plugins/styles-webpack-plugin.d.ts +19 -0
  45. package/src/webpack/plugins/styles-webpack-plugin.js +71 -0
  46. package/src/webpack/utils/helpers.d.ts +5 -1
  47. package/src/webpack/utils/helpers.js +24 -14
  48. package/src/webpack/utils/stats.d.ts +13 -8
  49. package/src/webpack/utils/stats.js +57 -6
  50. package/src/webpack/configs/analytics.d.ts +0 -11
  51. package/src/webpack/configs/analytics.js +0 -27
  52. package/src/webpack/plugins/analytics.d.ts +0 -66
  53. package/src/webpack/plugins/analytics.js +0 -236
@@ -33,54 +33,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getStylesConfig = exports.resolveGlobalStyles = void 0;
36
+ exports.getStylesConfig = void 0;
37
37
  const fs = __importStar(require("fs"));
38
38
  const mini_css_extract_plugin_1 = __importDefault(require("mini-css-extract-plugin"));
39
39
  const path = __importStar(require("path"));
40
+ const url_1 = require("url");
40
41
  const sass_service_1 = require("../../sass/sass-service");
41
42
  const sass_service_legacy_1 = require("../../sass/sass-service-legacy");
42
43
  const environment_options_1 = require("../../utils/environment-options");
43
44
  const plugins_1 = require("../plugins");
44
45
  const css_optimizer_plugin_1 = require("../plugins/css-optimizer-plugin");
46
+ const styles_webpack_plugin_1 = require("../plugins/styles-webpack-plugin");
45
47
  const helpers_1 = require("../utils/helpers");
46
- function resolveGlobalStyles(styleEntrypoints, root, preserveSymlinks, skipResolution = false) {
47
- const entryPoints = {};
48
- const noInjectNames = [];
49
- const paths = [];
50
- if (styleEntrypoints.length === 0) {
51
- return { entryPoints, noInjectNames, paths };
52
- }
53
- for (const style of (0, helpers_1.normalizeExtraEntryPoints)(styleEntrypoints, 'styles')) {
54
- let stylesheetPath = style.input;
55
- if (!skipResolution) {
56
- stylesheetPath = path.resolve(root, stylesheetPath);
57
- if (!fs.existsSync(stylesheetPath)) {
58
- try {
59
- stylesheetPath = require.resolve(style.input, { paths: [root] });
60
- }
61
- catch { }
62
- }
63
- }
64
- if (!preserveSymlinks) {
65
- stylesheetPath = fs.realpathSync(stylesheetPath);
66
- }
67
- // Add style entry points.
68
- if (entryPoints[style.bundleName]) {
69
- entryPoints[style.bundleName].push(stylesheetPath);
70
- }
71
- else {
72
- entryPoints[style.bundleName] = [stylesheetPath];
73
- }
74
- // Add non injected styles to the list.
75
- if (!style.inject) {
76
- noInjectNames.push(style.bundleName);
77
- }
78
- // Add global css paths.
79
- paths.push(stylesheetPath);
80
- }
81
- return { entryPoints, noInjectNames, paths };
82
- }
83
- exports.resolveGlobalStyles = resolveGlobalStyles;
84
48
  // eslint-disable-next-line max-lines-per-function
85
49
  function getStylesConfig(wco) {
86
50
  var _a, _b, _c;
@@ -93,10 +57,17 @@ function getStylesConfig(wco) {
93
57
  // use includePaths from appConfig
94
58
  const includePaths = (_c = (_b = (_a = buildOptions.stylePreprocessorOptions) === null || _a === void 0 ? void 0 : _a.includePaths) === null || _b === void 0 ? void 0 : _b.map((p) => path.resolve(root, p))) !== null && _c !== void 0 ? _c : [];
95
59
  // Process global styles.
96
- const { entryPoints, noInjectNames, paths: globalStylePaths, } = resolveGlobalStyles(buildOptions.styles, root, !!buildOptions.preserveSymlinks);
97
- if (noInjectNames.length > 0) {
98
- // Add plugin to remove hashes from lazy styles.
99
- extraPlugins.push(new plugins_1.RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
60
+ if (buildOptions.styles.length > 0) {
61
+ const { entryPoints, noInjectNames } = (0, helpers_1.normalizeGlobalStyles)(buildOptions.styles);
62
+ extraPlugins.push(new styles_webpack_plugin_1.StylesWebpackPlugin({
63
+ root,
64
+ entryPoints,
65
+ preserveSymlinks: buildOptions.preserveSymlinks,
66
+ }));
67
+ if (noInjectNames.length > 0) {
68
+ // Add plugin to remove hashes from lazy styles.
69
+ extraPlugins.push(new plugins_1.RemoveHashPlugin({ chunkNames: noInjectNames, hashFormat }));
70
+ }
100
71
  }
101
72
  const sassImplementation = environment_options_1.useLegacySass
102
73
  ? new sass_service_legacy_1.SassLegacyWorkerImplementation()
@@ -238,7 +209,7 @@ function getStylesConfig(wco) {
238
209
  },
239
210
  {
240
211
  loader: require.resolve('sass-loader'),
241
- options: getSassLoaderOptions(root, projectRoot, sassImplementation, includePaths, false, !buildOptions.verbose),
212
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, false, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
242
213
  },
243
214
  ],
244
215
  },
@@ -253,7 +224,7 @@ function getStylesConfig(wco) {
253
224
  },
254
225
  {
255
226
  loader: require.resolve('sass-loader'),
256
- options: getSassLoaderOptions(root, projectRoot, sassImplementation, includePaths, true, !buildOptions.verbose),
227
+ options: getSassLoaderOptions(root, sassImplementation, includePaths, true, !buildOptions.verbose, !!buildOptions.preserveSymlinks),
257
228
  },
258
229
  ],
259
230
  },
@@ -275,7 +246,6 @@ function getStylesConfig(wco) {
275
246
  },
276
247
  ];
277
248
  return {
278
- entry: entryPoints,
279
249
  module: {
280
250
  rules: styleLanguages.map(({ extensions, use }) => ({
281
251
  test: new RegExp(`\\.(?:${extensions.join('|')})$`, 'i'),
@@ -286,8 +256,7 @@ function getStylesConfig(wco) {
286
256
  // Global styles are only defined global styles
287
257
  {
288
258
  use: globalStyleLoaders,
289
- include: globalStylePaths,
290
- resourceQuery: { not: [/\?ngResource/] },
259
+ resourceQuery: /\?ngGlobalStyle/,
291
260
  },
292
261
  // Component styles are all styles except defined global styles
293
262
  {
@@ -330,24 +299,18 @@ function getTailwindConfigPath({ projectRoot, root }) {
330
299
  }
331
300
  return undefined;
332
301
  }
333
- function getSassLoaderOptions(root, projectRoot, implementation, includePaths, indentedSyntax, verbose) {
302
+ function getSassLoaderOptions(root, implementation, includePaths, indentedSyntax, verbose, preserveSymlinks) {
334
303
  return implementation instanceof sass_service_1.SassWorkerImplementation
335
304
  ? {
336
305
  sourceMap: true,
337
306
  api: 'modern',
338
307
  implementation,
339
- // Webpack importer is only implemented in the legacy API.
308
+ // Webpack importer is only implemented in the legacy API and we have our own custom Webpack importer.
340
309
  // See: https://github.com/webpack-contrib/sass-loader/blob/997f3eb41d86dd00d5fa49c395a1aeb41573108c/src/utils.js#L642-L651
341
310
  webpackImporter: false,
342
- sassOptions: {
343
- loadPaths: [
344
- ...includePaths,
345
- // Needed to resolve node packages and retain the same behaviour of with the legacy API as sass-loader resolves
346
- // scss also from the cwd and project root.
347
- // See: https://github.com/webpack-contrib/sass-loader/blob/997f3eb41d86dd00d5fa49c395a1aeb41573108c/src/utils.js#L307
348
- projectRoot,
349
- path.join(root, 'node_modules'),
350
- ],
311
+ sassOptions: (loaderContext) => ({
312
+ importers: [getSassResolutionImporter(loaderContext, root, preserveSymlinks)],
313
+ loadPaths: includePaths,
351
314
  // Use expanded as otherwise sass will remove comments that are needed for autoprefixer
352
315
  // Ex: /* autoprefixer grid: autoplace */
353
316
  // See: https://github.com/webpack-contrib/sass-loader/blob/45ad0be17264ceada5f0b4fb87e9357abe85c4ff/src/getSassOptions.js#L68-L70
@@ -356,7 +319,7 @@ function getSassLoaderOptions(root, projectRoot, implementation, includePaths, i
356
319
  quietDeps: !verbose,
357
320
  verbose,
358
321
  syntax: indentedSyntax ? 'indented' : 'scss',
359
- },
322
+ }),
360
323
  }
361
324
  : {
362
325
  sourceMap: true,
@@ -385,3 +348,50 @@ function getSassLoaderOptions(root, projectRoot, implementation, includePaths, i
385
348
  },
386
349
  };
387
350
  }
351
+ function getSassResolutionImporter(loaderContext, root, preserveSymlinks) {
352
+ const commonResolverOptions = {
353
+ conditionNames: ['sass', 'style'],
354
+ mainFields: ['sass', 'style', 'main', '...'],
355
+ extensions: ['.scss', '.sass', '.css'],
356
+ restrictions: [/\.((sa|sc|c)ss)$/i],
357
+ preferRelative: true,
358
+ symlinks: !preserveSymlinks,
359
+ };
360
+ // Sass also supports import-only files. If you name a file <name>.import.scss, it will only be loaded for imports, not for @uses.
361
+ // See: https://sass-lang.com/documentation/at-rules/import#import-only-files
362
+ const resolveImport = loaderContext.getResolve({
363
+ ...commonResolverOptions,
364
+ dependencyType: 'sass-import',
365
+ mainFiles: ['_index.import', '_index', 'index.import', 'index', '...'],
366
+ });
367
+ const resolveModule = loaderContext.getResolve({
368
+ ...commonResolverOptions,
369
+ dependencyType: 'sass-module',
370
+ mainFiles: ['_index', 'index', '...'],
371
+ });
372
+ return {
373
+ findFileUrl: async (url, { fromImport }) => {
374
+ if (url.charAt(0) === '.') {
375
+ // Let Sass handle relative imports.
376
+ return null;
377
+ }
378
+ let file;
379
+ const resolve = fromImport ? resolveImport : resolveModule;
380
+ try {
381
+ file = await resolve(root, url);
382
+ }
383
+ catch {
384
+ // Try to resolve a partial file
385
+ // @use '@material/button/button' as mdc-button;
386
+ // `@material/button/button` -> `@material/button/_button`
387
+ const lastSlashIndex = url.lastIndexOf('/');
388
+ const underscoreIndex = lastSlashIndex + 1;
389
+ if (underscoreIndex > 0 && url.charAt(underscoreIndex) !== '_') {
390
+ const partialFileUrl = `${url.slice(0, underscoreIndex)}_${url.slice(underscoreIndex)}`;
391
+ file = await resolve(root, partialFileUrl).catch(() => undefined);
392
+ }
393
+ }
394
+ return file ? (0, url_1.pathToFileURL)(file) : null;
395
+ },
396
+ };
397
+ }
@@ -0,0 +1,18 @@
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
+ export interface OccurrencesPluginOptions {
10
+ aot?: boolean;
11
+ scriptsOptimization?: boolean;
12
+ }
13
+ export declare class OccurrencesPlugin {
14
+ private options;
15
+ constructor(options: OccurrencesPluginOptions);
16
+ apply(compiler: Compiler): void;
17
+ private countOccurrences;
18
+ }
@@ -0,0 +1,79 @@
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.OccurrencesPlugin = void 0;
11
+ const PLUGIN_NAME = 'angular-occurrences-plugin';
12
+ class OccurrencesPlugin {
13
+ constructor(options) {
14
+ this.options = options;
15
+ }
16
+ apply(compiler) {
17
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
18
+ compilation.hooks.processAssets.tapPromise({
19
+ name: PLUGIN_NAME,
20
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE,
21
+ }, async (compilationAssets) => {
22
+ for (const assetName of Object.keys(compilationAssets)) {
23
+ if (!assetName.endsWith('.js')) {
24
+ continue;
25
+ }
26
+ const scriptAsset = compilation.getAsset(assetName);
27
+ if (!scriptAsset || scriptAsset.source.size() <= 0) {
28
+ continue;
29
+ }
30
+ const src = scriptAsset.source.source().toString('utf-8');
31
+ let ngComponentCount = 0;
32
+ if (!this.options.aot) {
33
+ // Count the number of `Component({` strings (case sensitive), which happens in __decorate().
34
+ ngComponentCount += this.countOccurrences(src, 'Component({');
35
+ }
36
+ if (this.options.scriptsOptimization) {
37
+ // for ascii_only true
38
+ ngComponentCount += this.countOccurrences(src, '.\\u0275cmp', false);
39
+ }
40
+ else {
41
+ // For Ivy we just count ɵcmp.src
42
+ ngComponentCount += this.countOccurrences(src, '.ɵcmp', true);
43
+ }
44
+ compilation.updateAsset(assetName, (s) => s, (assetInfo) => ({
45
+ ...assetInfo,
46
+ ngComponentCount,
47
+ }));
48
+ }
49
+ });
50
+ });
51
+ }
52
+ countOccurrences(source, match, wordBreak = false) {
53
+ let count = 0;
54
+ // We condition here so branch prediction happens out of the loop, not in it.
55
+ if (wordBreak) {
56
+ const re = /\w/;
57
+ for (let pos = source.lastIndexOf(match); pos >= 0; pos = source.lastIndexOf(match, pos)) {
58
+ if (!(re.test(source[pos - 1] || '') || re.test(source[pos + match.length] || ''))) {
59
+ count++; // 1 match, AH! AH! AH! 2 matches, AH! AH! AH!
60
+ }
61
+ pos -= match.length;
62
+ if (pos < 0) {
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ else {
68
+ for (let pos = source.lastIndexOf(match); pos >= 0; pos = source.lastIndexOf(match, pos)) {
69
+ count++; // 1 match, AH! AH! AH! 2 matches, AH! AH! AH!
70
+ pos -= match.length;
71
+ if (pos < 0) {
72
+ break;
73
+ }
74
+ }
75
+ }
76
+ return count;
77
+ }
78
+ }
79
+ exports.OccurrencesPlugin = OccurrencesPlugin;
@@ -34,6 +34,8 @@ exports.ScriptsWebpackPlugin = void 0;
34
34
  const loader_utils_1 = require("loader-utils");
35
35
  const path = __importStar(require("path"));
36
36
  const webpack_1 = require("webpack");
37
+ const error_1 = require("../../utils/error");
38
+ const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
37
39
  const Entrypoint = require('webpack/lib/Entrypoint');
38
40
  /**
39
41
  * The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
@@ -81,18 +83,35 @@ class ScriptsWebpackPlugin {
81
83
  chunk.addGroup(entrypoint);
82
84
  compilation.entrypoints.set(this.options.name, entrypoint);
83
85
  compilation.chunks.add(chunk);
84
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
86
  compilation.assets[filename] = source;
86
87
  compilation.hooks.chunkAsset.call(chunk, filename);
87
88
  }
88
89
  apply(compiler) {
89
- if (!this.options.scripts || this.options.scripts.length === 0) {
90
+ if (this.options.scripts.length === 0) {
90
91
  return;
91
92
  }
92
- const scripts = this.options.scripts
93
- .filter((script) => !!script)
94
- .map((script) => path.resolve(this.options.basePath || '', script));
93
+ const resolver = compiler.resolverFactory.get('normal', {
94
+ preferRelative: true,
95
+ useSyncFileSystemCalls: true,
96
+ fileSystem: compiler.inputFileSystem,
97
+ });
95
98
  compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
99
+ const scripts = [];
100
+ for (const script of this.options.scripts) {
101
+ try {
102
+ const resolvedPath = resolver.resolveSync({}, this.options.basePath, script);
103
+ if (resolvedPath) {
104
+ scripts.push(resolvedPath);
105
+ }
106
+ else {
107
+ (0, webpack_diagnostics_1.addError)(compilation, `Cannot resolve '${script}'.`);
108
+ }
109
+ }
110
+ catch (error) {
111
+ (0, error_1.assertIsError)(error);
112
+ (0, webpack_diagnostics_1.addError)(compilation, error.message);
113
+ }
114
+ }
96
115
  compilation.hooks.additionalAssets.tapPromise(PLUGIN_NAME, async () => {
97
116
  if (await this.shouldSkip(compilation, scripts)) {
98
117
  if (this._cachedOutput) {
@@ -0,0 +1,19 @@
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 type { Compiler } from 'webpack';
9
+ export interface StylesWebpackPluginOptions {
10
+ preserveSymlinks?: boolean;
11
+ root: string;
12
+ entryPoints: Record<string, string[]>;
13
+ }
14
+ export declare class StylesWebpackPlugin {
15
+ private readonly options;
16
+ private compilation;
17
+ constructor(options: StylesWebpackPluginOptions);
18
+ apply(compiler: Compiler): void;
19
+ }
@@ -0,0 +1,71 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.StylesWebpackPlugin = void 0;
14
+ const assert_1 = __importDefault(require("assert"));
15
+ const error_1 = require("../../utils/error");
16
+ const webpack_diagnostics_1 = require("../../utils/webpack-diagnostics");
17
+ /**
18
+ * The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
19
+ */
20
+ const PLUGIN_NAME = 'styles-webpack-plugin';
21
+ class StylesWebpackPlugin {
22
+ constructor(options) {
23
+ this.options = options;
24
+ }
25
+ apply(compiler) {
26
+ const { entryPoints, preserveSymlinks, root } = this.options;
27
+ const webpackOptions = compiler.options;
28
+ const entry = typeof webpackOptions.entry === 'function' ? webpackOptions.entry() : webpackOptions.entry;
29
+ const resolver = compiler.resolverFactory.get('global-styles', {
30
+ conditionNames: ['sass', 'less', 'style'],
31
+ mainFields: ['sass', 'less', 'style', 'main', '...'],
32
+ extensions: ['.scss', '.sass', '.less', '.css'],
33
+ restrictions: [/\.((le|sa|sc|c)ss)$/i],
34
+ preferRelative: true,
35
+ useSyncFileSystemCalls: true,
36
+ symlinks: !preserveSymlinks,
37
+ fileSystem: compiler.inputFileSystem,
38
+ });
39
+ webpackOptions.entry = async () => {
40
+ var _a, _b;
41
+ var _c;
42
+ const entrypoints = await entry;
43
+ for (const [bundleName, paths] of Object.entries(entryPoints)) {
44
+ (_a = entrypoints[bundleName]) !== null && _a !== void 0 ? _a : (entrypoints[bundleName] = {});
45
+ const entryImport = ((_b = (_c = entrypoints[bundleName]).import) !== null && _b !== void 0 ? _b : (_c.import = []));
46
+ for (const path of paths) {
47
+ try {
48
+ const resolvedPath = resolver.resolveSync({}, root, path);
49
+ if (resolvedPath) {
50
+ entryImport.push(`${resolvedPath}?ngGlobalStyle`);
51
+ }
52
+ else {
53
+ (0, assert_1.default)(this.compilation, 'Compilation cannot be undefined.');
54
+ (0, webpack_diagnostics_1.addError)(this.compilation, `Cannot resolve '${path}'.`);
55
+ }
56
+ }
57
+ catch (error) {
58
+ (0, assert_1.default)(this.compilation, 'Compilation cannot be undefined.');
59
+ (0, error_1.assertIsError)(error);
60
+ (0, webpack_diagnostics_1.addError)(this.compilation, error.message);
61
+ }
62
+ }
63
+ }
64
+ return entrypoints;
65
+ };
66
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
67
+ this.compilation = compilation;
68
+ });
69
+ }
70
+ }
71
+ exports.StylesWebpackPlugin = StylesWebpackPlugin;
@@ -21,8 +21,12 @@ export declare type NormalizedEntryPoint = Required<Exclude<ScriptElement | Styl
21
21
  export declare function normalizeExtraEntryPoints(extraEntryPoints: (ScriptElement | StyleElement)[], defaultBundleName: string): NormalizedEntryPoint[];
22
22
  export declare function assetNameTemplateFactory(hashFormat: HashFormat): (resourcePath: string) => string;
23
23
  export declare function getInstrumentationExcludedPaths(root: string, excludedPaths: string[]): Set<string>;
24
+ export declare function normalizeGlobalStyles(styleEntrypoints: StyleElement[]): {
25
+ entryPoints: Record<string, string[]>;
26
+ noInjectNames: string[];
27
+ };
24
28
  export declare function getCacheSettings(wco: WebpackConfigOptions, angularVersion: string): WebpackOptionsNormalized['cache'];
25
- export declare function globalScriptsByBundleName(root: string, scripts: ScriptElement[]): {
29
+ export declare function globalScriptsByBundleName(scripts: ScriptElement[]): {
26
30
  bundleName: string;
27
31
  inject: boolean;
28
32
  paths: string[];
@@ -33,9 +33,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
36
+ exports.getStatsOptions = exports.assetPatterns = exports.globalScriptsByBundleName = exports.getCacheSettings = exports.normalizeGlobalStyles = exports.getInstrumentationExcludedPaths = exports.assetNameTemplateFactory = exports.normalizeExtraEntryPoints = exports.getOutputHashFormat = void 0;
37
37
  const crypto_1 = require("crypto");
38
- const fs_1 = require("fs");
39
38
  const glob_1 = __importDefault(require("glob"));
40
39
  const path = __importStar(require("path"));
41
40
  const schema_1 = require("../../builders/browser/schema");
@@ -130,6 +129,26 @@ function getInstrumentationExcludedPaths(root, excludedPaths) {
130
129
  return excluded;
131
130
  }
132
131
  exports.getInstrumentationExcludedPaths = getInstrumentationExcludedPaths;
132
+ function normalizeGlobalStyles(styleEntrypoints) {
133
+ var _a;
134
+ var _b;
135
+ const entryPoints = {};
136
+ const noInjectNames = [];
137
+ if (styleEntrypoints.length === 0) {
138
+ return { entryPoints, noInjectNames };
139
+ }
140
+ for (const style of normalizeExtraEntryPoints(styleEntrypoints, 'styles')) {
141
+ // Add style entry points.
142
+ (_a = entryPoints[_b = style.bundleName]) !== null && _a !== void 0 ? _a : (entryPoints[_b] = []);
143
+ entryPoints[style.bundleName].push(style.input);
144
+ // Add non injected styles to the list.
145
+ if (!style.inject) {
146
+ noInjectNames.push(style.bundleName);
147
+ }
148
+ }
149
+ return { entryPoints, noInjectNames };
150
+ }
151
+ exports.normalizeGlobalStyles = normalizeGlobalStyles;
133
152
  function getCacheSettings(wco, angularVersion) {
134
153
  const { enabled, path: cacheDirectory } = wco.buildOptions.cache;
135
154
  if (enabled) {
@@ -164,31 +183,22 @@ function getCacheSettings(wco, angularVersion) {
164
183
  return false;
165
184
  }
166
185
  exports.getCacheSettings = getCacheSettings;
167
- function globalScriptsByBundleName(root, scripts) {
186
+ function globalScriptsByBundleName(scripts) {
168
187
  return normalizeExtraEntryPoints(scripts, 'scripts').reduce((prev, curr) => {
169
188
  const { bundleName, inject, input } = curr;
170
- let resolvedPath = path.resolve(root, input);
171
- if (!(0, fs_1.existsSync)(resolvedPath)) {
172
- try {
173
- resolvedPath = require.resolve(input, { paths: [root] });
174
- }
175
- catch {
176
- throw new Error(`Script file ${input} does not exist.`);
177
- }
178
- }
179
189
  const existingEntry = prev.find((el) => el.bundleName === bundleName);
180
190
  if (existingEntry) {
181
191
  if (existingEntry.inject && !inject) {
182
192
  // All entries have to be lazy for the bundle to be lazy.
183
193
  throw new Error(`The ${bundleName} bundle is mixing injected and non-injected scripts.`);
184
194
  }
185
- existingEntry.paths.push(resolvedPath);
195
+ existingEntry.paths.push(input);
186
196
  }
187
197
  else {
188
198
  prev.push({
189
199
  bundleName,
190
200
  inject,
191
- paths: [resolvedPath],
201
+ paths: [input],
192
202
  });
193
203
  }
194
204
  return prev;
@@ -22,17 +22,22 @@ export interface BundleStats {
22
22
  initial: boolean;
23
23
  stats: BundleStatsData;
24
24
  }
25
- export declare function generateBundleStats(info: {
26
- rawSize?: number;
27
- estimatedTransferSize?: number;
28
- files?: string[];
29
- names?: string[];
30
- initial?: boolean;
31
- rendered?: boolean;
32
- }): BundleStats;
33
25
  export declare function statsWarningsToString(json: StatsCompilation, statsConfig: WebpackStatsOptions): string;
34
26
  export declare function statsErrorsToString(json: StatsCompilation, statsConfig: WebpackStatsOptions): string;
35
27
  export declare function statsHasErrors(json: StatsCompilation): boolean;
36
28
  export declare function statsHasWarnings(json: StatsCompilation): boolean;
37
29
  export declare function createWebpackLoggingCallback(options: BrowserBuilderOptions, logger: logging.LoggerApi): WebpackLoggingCallback;
30
+ export interface BuildEventStats {
31
+ aot: boolean;
32
+ optimization: boolean;
33
+ allChunksCount: number;
34
+ lazyChunksCount: number;
35
+ initialChunksCount: number;
36
+ changedChunksCount?: number;
37
+ durationInMs: number;
38
+ cssSizeInBytes: number;
39
+ jsSizeInBytes: number;
40
+ ngComponentCount: number;
41
+ }
42
+ export declare function generateBuildEventStats(webpackStats: StatsCompilation, browserBuilderOptions: BrowserBuilderOptions): BuildEventStats;
38
43
  export declare function webpackStatsLogger(logger: logging.LoggerApi, json: StatsCompilation, config: Configuration, budgetFailures?: BudgetCalculatorResult[]): void;
@@ -33,10 +33,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
34
  };
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.webpackStatsLogger = exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.generateBundleStats = exports.formatSize = void 0;
36
+ exports.webpackStatsLogger = exports.generateBuildEventStats = exports.createWebpackLoggingCallback = exports.statsHasWarnings = exports.statsHasErrors = exports.statsErrorsToString = exports.statsWarningsToString = exports.formatSize = void 0;
37
37
  const core_1 = require("@angular-devkit/core");
38
+ const assert_1 = __importDefault(require("assert"));
38
39
  const path = __importStar(require("path"));
39
40
  const text_table_1 = __importDefault(require("text-table"));
41
+ const utils_1 = require("../../utils");
40
42
  const color_1 = require("../../utils/color");
41
43
  const async_chunks_1 = require("./async-chunks");
42
44
  const helpers_1 = require("./helpers");
@@ -52,6 +54,11 @@ function formatSize(size) {
52
54
  return `${roundedSize.toFixed(fractionDigits)} ${abbreviations[index]}`;
53
55
  }
54
56
  exports.formatSize = formatSize;
57
+ function getBuildDuration(webpackStats) {
58
+ (0, assert_1.default)(webpackStats.builtAt, 'buildAt cannot be undefined');
59
+ (0, assert_1.default)(webpackStats.time, 'time cannot be undefined');
60
+ return Date.now() - webpackStats.builtAt + webpackStats.time;
61
+ }
55
62
  function generateBundleStats(info) {
56
63
  var _a, _b, _c;
57
64
  const rawSize = typeof info.rawSize === 'number' ? info.rawSize : '-';
@@ -64,7 +71,6 @@ function generateBundleStats(info) {
64
71
  stats: [files, names, rawSize, estimatedTransferSize],
65
72
  };
66
73
  }
67
- exports.generateBundleStats = generateBundleStats;
68
74
  function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize, budgetFailures) {
69
75
  const g = (x) => (colors ? color_1.colors.greenBright(x) : x);
70
76
  const c = (x) => (colors ? color_1.colors.cyanBright(x) : x);
@@ -238,10 +244,7 @@ statsConfig, budgetFailures) {
238
244
  // In some cases we do things outside of webpack context
239
245
  // Such us index generation, service worker augmentation etc...
240
246
  // This will correct the time and include these.
241
- let time = 0;
242
- if (json.builtAt !== undefined && json.time !== undefined) {
243
- time = Date.now() - json.builtAt + json.time;
244
- }
247
+ const time = getBuildDuration(json);
245
248
  if (unchangedChunkNumber > 0) {
246
249
  return ('\n' +
247
250
  rs(core_1.tags.stripIndents `
@@ -370,6 +373,54 @@ function createWebpackLoggingCallback(options, logger) {
370
373
  };
371
374
  }
372
375
  exports.createWebpackLoggingCallback = createWebpackLoggingCallback;
376
+ function generateBuildEventStats(webpackStats, browserBuilderOptions) {
377
+ var _a, _b;
378
+ const { chunks = [], assets = [] } = webpackStats;
379
+ let jsSizeInBytes = 0;
380
+ let cssSizeInBytes = 0;
381
+ let initialChunksCount = 0;
382
+ let ngComponentCount = 0;
383
+ let changedChunksCount = 0;
384
+ const allChunksCount = chunks.length;
385
+ const isFirstRun = !runsCache.has(webpackStats.outputPath || '');
386
+ const chunkFiles = new Set();
387
+ for (const chunk of chunks) {
388
+ if (!isFirstRun && chunk.rendered) {
389
+ changedChunksCount++;
390
+ }
391
+ if (chunk.initial) {
392
+ initialChunksCount++;
393
+ }
394
+ for (const file of (_a = chunk.files) !== null && _a !== void 0 ? _a : []) {
395
+ chunkFiles.add(file);
396
+ }
397
+ }
398
+ for (const asset of assets) {
399
+ if (asset.name.endsWith('.map') || !chunkFiles.has(asset.name)) {
400
+ continue;
401
+ }
402
+ if (asset.name.endsWith('.js')) {
403
+ jsSizeInBytes += asset.size;
404
+ ngComponentCount += (_b = asset.info.ngComponentCount) !== null && _b !== void 0 ? _b : 0;
405
+ }
406
+ else if (asset.name.endsWith('.css')) {
407
+ cssSizeInBytes += asset.size;
408
+ }
409
+ }
410
+ return {
411
+ optimization: !!(0, utils_1.normalizeOptimization)(browserBuilderOptions.optimization).scripts,
412
+ aot: browserBuilderOptions.aot !== false,
413
+ allChunksCount,
414
+ lazyChunksCount: allChunksCount - initialChunksCount,
415
+ initialChunksCount,
416
+ changedChunksCount,
417
+ durationInMs: getBuildDuration(webpackStats),
418
+ cssSizeInBytes,
419
+ jsSizeInBytes,
420
+ ngComponentCount,
421
+ };
422
+ }
423
+ exports.generateBuildEventStats = generateBuildEventStats;
373
424
  function webpackStatsLogger(logger, json, config, budgetFailures) {
374
425
  logger.info(statsToString(json, config.stats, budgetFailures));
375
426
  if (typeof config.stats !== 'object') {