@angular-devkit/build-angular 13.1.0-next.1 → 13.1.0-next.2

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 CHANGED
@@ -1,45 +1,46 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "13.1.0-next.1",
3
+ "version": "13.1.0-next.2",
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
9
  "@ampproject/remapping": "1.0.1",
10
- "@angular-devkit/architect": "0.1301.0-next.1",
11
- "@angular-devkit/build-webpack": "0.1301.0-next.1",
12
- "@angular-devkit/core": "13.1.0-next.1",
10
+ "@angular-devkit/architect": "0.1301.0-next.2",
11
+ "@angular-devkit/build-webpack": "0.1301.0-next.2",
12
+ "@angular-devkit/core": "13.1.0-next.2",
13
13
  "@babel/core": "7.16.0",
14
14
  "@babel/generator": "7.16.0",
15
15
  "@babel/helper-annotate-as-pure": "7.16.0",
16
- "@babel/plugin-proposal-async-generator-functions": "7.16.0",
16
+ "@babel/plugin-proposal-async-generator-functions": "7.16.4",
17
17
  "@babel/plugin-transform-async-to-generator": "7.16.0",
18
- "@babel/plugin-transform-runtime": "7.16.0",
19
- "@babel/preset-env": "7.16.0",
18
+ "@babel/plugin-transform-runtime": "7.16.4",
19
+ "@babel/preset-env": "7.16.4",
20
20
  "@babel/runtime": "7.16.3",
21
21
  "@babel/template": "7.16.0",
22
22
  "@discoveryjs/json-ext": "0.5.5",
23
- "@ngtools/webpack": "13.1.0-next.1",
23
+ "@ngtools/webpack": "13.1.0-next.2",
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": "9.0.1",
30
+ "copy-webpack-plugin": "9.1.0",
31
31
  "core-js": "3.19.1",
32
32
  "critters": "0.0.14",
33
33
  "css-loader": "6.5.1",
34
- "esbuild-wasm": "0.13.13",
34
+ "esbuild-wasm": "0.13.14",
35
35
  "glob": "7.2.0",
36
36
  "https-proxy-agent": "5.0.0",
37
37
  "inquirer": "8.2.0",
38
+ "jsonc-parser": "3.0.0",
38
39
  "karma-source-map-support": "1.4.0",
39
40
  "less": "4.1.2",
40
41
  "less-loader": "10.2.0",
41
- "license-webpack-plugin": "3.0.0",
42
- "loader-utils": "3.1.3",
42
+ "license-webpack-plugin": "4.0.0",
43
+ "loader-utils": "3.2.0",
43
44
  "mini-css-extract-plugin": "2.4.4",
44
45
  "minimatch": "3.0.4",
45
46
  "open": "8.4.0",
@@ -60,18 +61,18 @@
60
61
  "source-map-support": "0.5.20",
61
62
  "stylus": "0.55.0",
62
63
  "stylus-loader": "6.2.0",
63
- "terser": "5.9.0",
64
+ "terser": "5.10.0",
64
65
  "text-table": "0.2.0",
65
66
  "tree-kill": "1.2.2",
66
67
  "tslib": "2.3.1",
67
- "webpack": "5.63.0",
68
+ "webpack": "5.64.1",
68
69
  "webpack-dev-middleware": "5.2.1",
69
- "webpack-dev-server": "4.4.0",
70
+ "webpack-dev-server": "4.5.0",
70
71
  "webpack-merge": "5.8.0",
71
72
  "webpack-subresource-integrity": "5.0.0"
72
73
  },
73
74
  "optionalDependencies": {
74
- "esbuild": "0.13.13"
75
+ "esbuild": "0.13.14"
75
76
  },
76
77
  "peerDependencies": {
77
78
  "@angular/compiler-cli": "^13.0.0 || ^13.1.0-next",
@@ -40,6 +40,7 @@ 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
42
  const progress_plugin_1 = require("../plugins/progress-plugin");
43
+ const transfer_size_plugin_1 = require("../plugins/transfer-size-plugin");
43
44
  const typescript_2 = require("../plugins/typescript");
44
45
  const helpers_1 = require("../utils/helpers");
45
46
  // eslint-disable-next-line max-lines-per-function
@@ -207,6 +208,9 @@ async function getCommonConfig(wco) {
207
208
  advanced: buildOptions.buildOptimizer,
208
209
  }));
209
210
  }
211
+ if (platform === 'browser' && (scriptsOptimization || stylesOptimization.minify)) {
212
+ extraMinimizers.push(new transfer_size_plugin_1.TransferSizePlugin());
213
+ }
210
214
  const externals = [...externalDependencies];
211
215
  if (isPlatformServer && !bundleDependencies) {
212
216
  externals.push(({ context, request }, callback) => (0, helpers_1.externalizePackages)(context !== null && context !== void 0 ? context : wco.projectRoot, request, callback));
@@ -318,6 +322,7 @@ async function getCommonConfig(wco) {
318
322
  ],
319
323
  },
320
324
  experiments: {
325
+ backCompat: false,
321
326
  syncWebAssembly: true,
322
327
  asyncWebAssembly: true,
323
328
  },
@@ -89,7 +89,7 @@ async function getDevServerConfig(wco) {
89
89
  },
90
90
  compress: false,
91
91
  static: false,
92
- https: getSslConfig(root, wco.buildOptions),
92
+ server: getServerConfig(root, wco.buildOptions),
93
93
  allowedHosts: getAllowedHostsConfig(wco.buildOptions),
94
94
  devMiddleware: {
95
95
  publicPath: servePath,
@@ -139,15 +139,20 @@ exports.buildServePath = buildServePath;
139
139
  * Private method to enhance a webpack config with SSL configuration.
140
140
  * @private
141
141
  */
142
- function getSslConfig(root, options) {
142
+ function getServerConfig(root, options) {
143
143
  const { ssl, sslCert, sslKey } = options;
144
- if (ssl && sslCert && sslKey) {
145
- return {
146
- key: (0, path_1.resolve)(root, sslKey),
147
- cert: (0, path_1.resolve)(root, sslCert),
148
- };
144
+ if (!ssl) {
145
+ return 'http';
149
146
  }
150
- return ssl;
147
+ return {
148
+ type: 'https',
149
+ options: sslCert && sslKey
150
+ ? {
151
+ key: (0, path_1.resolve)(root, sslKey),
152
+ cert: (0, path_1.resolve)(root, sslCert),
153
+ }
154
+ : undefined,
155
+ };
151
156
  }
152
157
  /**
153
158
  * Private method to enhance a webpack config with Proxy configuration.
@@ -158,21 +163,71 @@ async function addProxyConfig(root, proxyConfig) {
158
163
  return undefined;
159
164
  }
160
165
  const proxyPath = (0, path_1.resolve)(root, proxyConfig);
161
- if ((0, fs_1.existsSync)(proxyPath)) {
162
- try {
163
- return require(proxyPath);
166
+ if (!(0, fs_1.existsSync)(proxyPath)) {
167
+ throw new Error(`Proxy configuration file ${proxyPath} does not exist.`);
168
+ }
169
+ switch ((0, path_1.extname)(proxyPath)) {
170
+ case '.json': {
171
+ const content = await fs_1.promises.readFile(proxyPath, 'utf-8');
172
+ const { parse, printParseErrorCode } = await Promise.resolve().then(() => __importStar(require('jsonc-parser')));
173
+ const parseErrors = [];
174
+ const proxyConfiguration = parse(content, parseErrors, { allowTrailingComma: true });
175
+ if (parseErrors.length > 0) {
176
+ let errorMessage = `Proxy configuration file ${proxyPath} contains parse errors:`;
177
+ for (const parseError of parseErrors) {
178
+ const { line, column } = getJsonErrorLineColumn(parseError.offset, content);
179
+ errorMessage += `\n[${line}, ${column}] ${printParseErrorCode(parseError.error)}`;
180
+ }
181
+ throw new Error(errorMessage);
182
+ }
183
+ return proxyConfiguration;
164
184
  }
165
- catch (e) {
166
- if (e.code === 'ERR_REQUIRE_ESM') {
167
- // Load the ESM configuration file using the TypeScript dynamic import workaround.
168
- // Once TypeScript provides support for keeping the dynamic import this workaround can be
169
- // changed to a direct dynamic import.
170
- return (await (0, load_esm_1.loadEsmModule)(url.pathToFileURL(proxyPath))).default;
185
+ case '.mjs':
186
+ // Load the ESM configuration file using the TypeScript dynamic import workaround.
187
+ // Once TypeScript provides support for keeping the dynamic import this workaround can be
188
+ // changed to a direct dynamic import.
189
+ return (await (0, load_esm_1.loadEsmModule)(url.pathToFileURL(proxyPath))).default;
190
+ case '.cjs':
191
+ return require(proxyPath);
192
+ default:
193
+ // The file could be either CommonJS or ESM.
194
+ // CommonJS is tried first then ESM if loading fails.
195
+ try {
196
+ return require(proxyPath);
171
197
  }
172
- throw e;
198
+ catch (e) {
199
+ if (e.code === 'ERR_REQUIRE_ESM') {
200
+ // Load the ESM configuration file using the TypeScript dynamic import workaround.
201
+ // Once TypeScript provides support for keeping the dynamic import this workaround can be
202
+ // changed to a direct dynamic import.
203
+ return (await (0, load_esm_1.loadEsmModule)(url.pathToFileURL(proxyPath))).default;
204
+ }
205
+ throw e;
206
+ }
207
+ }
208
+ }
209
+ /**
210
+ * Calculates the line and column for an error offset in the content of a JSON file.
211
+ * @param location The offset error location from the beginning of the content.
212
+ * @param content The full content of the file containing the error.
213
+ * @returns An object containing the line and column
214
+ */
215
+ function getJsonErrorLineColumn(offset, content) {
216
+ if (offset === 0) {
217
+ return { line: 1, column: 1 };
218
+ }
219
+ let line = 0;
220
+ let position = 0;
221
+ // eslint-disable-next-line no-constant-condition
222
+ while (true) {
223
+ ++line;
224
+ const nextNewline = content.indexOf('\n', position);
225
+ if (nextNewline === -1 || nextNewline > offset) {
226
+ break;
173
227
  }
228
+ position = nextNewline + 1;
174
229
  }
175
- throw new Error('Proxy config file ' + proxyPath + ' does not exist.');
230
+ return { line, column: offset - position + 1 };
176
231
  }
177
232
  /**
178
233
  * Find the default server path. We don't want to expose baseHref and deployUrl as arguments, only
@@ -0,0 +1,12 @@
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 declare class TransferSizePlugin {
10
+ constructor();
11
+ apply(compiler: Compiler): void;
12
+ }
@@ -0,0 +1,47 @@
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.TransferSizePlugin = void 0;
11
+ const util_1 = require("util");
12
+ const zlib_1 = require("zlib");
13
+ const brotliCompressAsync = (0, util_1.promisify)(zlib_1.brotliCompress);
14
+ const PLUGIN_NAME = 'angular-transfer-size-estimator';
15
+ class TransferSizePlugin {
16
+ constructor() { }
17
+ apply(compiler) {
18
+ compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
19
+ compilation.hooks.processAssets.tapPromise({
20
+ name: PLUGIN_NAME,
21
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ANALYSE,
22
+ }, async (compilationAssets) => {
23
+ const actions = [];
24
+ for (const assetName of Object.keys(compilationAssets)) {
25
+ if (!assetName.endsWith('.js') && !assetName.endsWith('.css')) {
26
+ continue;
27
+ }
28
+ const scriptAsset = compilation.getAsset(assetName);
29
+ if (!scriptAsset || scriptAsset.source.size() <= 0) {
30
+ continue;
31
+ }
32
+ actions.push(brotliCompressAsync(scriptAsset.source.source())
33
+ .then((result) => {
34
+ compilation.updateAsset(assetName, (s) => s, {
35
+ estimatedTransferSize: result.length,
36
+ });
37
+ })
38
+ .catch((error) => {
39
+ compilation.warnings.push(new compilation.compiler.webpack.WebpackError(`Unable to calculate estimated transfer size for '${assetName}'. Reason: ${error.message}`));
40
+ }));
41
+ }
42
+ await Promise.all(actions);
43
+ });
44
+ });
45
+ }
46
+ }
47
+ exports.TransferSizePlugin = TransferSizePlugin;
@@ -10,13 +10,19 @@ import { logging } from '@angular-devkit/core';
10
10
  import { Configuration, StatsCompilation } from 'webpack';
11
11
  import { Schema as BrowserBuilderOptions } from '../../builders/browser/schema';
12
12
  export declare function formatSize(size: number): string;
13
- export declare type BundleStatsData = [files: string, names: string, size: number | string];
13
+ export declare type BundleStatsData = [
14
+ files: string,
15
+ names: string,
16
+ rawSize: number | string,
17
+ estimatedTransferSize: number | string
18
+ ];
14
19
  export interface BundleStats {
15
20
  initial: boolean;
16
21
  stats: BundleStatsData;
17
22
  }
18
23
  export declare function generateBundleStats(info: {
19
- size?: number;
24
+ rawSize?: number;
25
+ estimatedTransferSize?: number;
20
26
  files?: string[];
21
27
  names?: string[];
22
28
  initial?: boolean;
@@ -50,35 +50,52 @@ function formatSize(size) {
50
50
  exports.formatSize = formatSize;
51
51
  function generateBundleStats(info) {
52
52
  var _a, _b, _c;
53
- const size = typeof info.size === 'number' ? info.size : '-';
53
+ const rawSize = typeof info.rawSize === 'number' ? info.rawSize : '-';
54
+ const estimatedTransferSize = typeof info.estimatedTransferSize === 'number' ? info.estimatedTransferSize : '-';
54
55
  const files = (_b = (_a = info.files) === null || _a === void 0 ? void 0 : _a.filter((f) => !f.endsWith('.map')).map((f) => path.basename(f)).join(', ')) !== null && _b !== void 0 ? _b : '';
55
56
  const names = ((_c = info.names) === null || _c === void 0 ? void 0 : _c.length) ? info.names.join(', ') : '-';
56
57
  const initial = !!info.initial;
57
58
  return {
58
59
  initial,
59
- stats: [files, names, size],
60
+ stats: [files, names, rawSize, estimatedTransferSize],
60
61
  };
61
62
  }
62
63
  exports.generateBundleStats = generateBundleStats;
63
- function generateBuildStatsTable(data, colors, showTotalSize) {
64
+ function generateBuildStatsTable(data, colors, showTotalSize, showEstimatedTransferSize) {
64
65
  const g = (x) => (colors ? color_1.colors.greenBright(x) : x);
65
66
  const c = (x) => (colors ? color_1.colors.cyanBright(x) : x);
66
67
  const bold = (x) => (colors ? color_1.colors.bold(x) : x);
67
68
  const dim = (x) => (colors ? color_1.colors.dim(x) : x);
68
69
  const changedEntryChunksStats = [];
69
70
  const changedLazyChunksStats = [];
70
- let initialTotalSize = 0;
71
+ let initialTotalRawSize = 0;
72
+ let initialTotalEstimatedTransferSize;
71
73
  for (const { initial, stats } of data) {
72
- const [files, names, size] = stats;
73
- const data = [
74
- g(files),
75
- names,
76
- c(typeof size === 'number' ? formatSize(size) : size),
77
- ];
74
+ const [files, names, rawSize, estimatedTransferSize] = stats;
75
+ let data;
76
+ if (showEstimatedTransferSize) {
77
+ data = [
78
+ g(files),
79
+ names,
80
+ c(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize),
81
+ c(typeof estimatedTransferSize === 'number'
82
+ ? formatSize(estimatedTransferSize)
83
+ : estimatedTransferSize),
84
+ ];
85
+ }
86
+ else {
87
+ data = [g(files), names, c(typeof rawSize === 'number' ? formatSize(rawSize) : rawSize), ''];
88
+ }
78
89
  if (initial) {
79
90
  changedEntryChunksStats.push(data);
80
- if (typeof size === 'number') {
81
- initialTotalSize += size;
91
+ if (typeof rawSize === 'number') {
92
+ initialTotalRawSize += rawSize;
93
+ }
94
+ if (showEstimatedTransferSize && typeof estimatedTransferSize === 'number') {
95
+ if (initialTotalEstimatedTransferSize === undefined) {
96
+ initialTotalEstimatedTransferSize = 0;
97
+ }
98
+ initialTotalEstimatedTransferSize += estimatedTransferSize;
82
99
  }
83
100
  }
84
101
  else {
@@ -86,12 +103,24 @@ function generateBuildStatsTable(data, colors, showTotalSize) {
86
103
  }
87
104
  }
88
105
  const bundleInfo = [];
106
+ const baseTitles = ['Names', 'Raw Size'];
107
+ const tableAlign = ['l', 'l', 'r'];
108
+ if (showEstimatedTransferSize) {
109
+ baseTitles.push('Estimated Transfer Size');
110
+ tableAlign.push('r');
111
+ }
89
112
  // Entry chunks
90
113
  if (changedEntryChunksStats.length) {
91
- bundleInfo.push(['Initial Chunk Files', 'Names', 'Size'].map(bold), ...changedEntryChunksStats);
114
+ bundleInfo.push(['Initial Chunk Files', ...baseTitles].map(bold), ...changedEntryChunksStats);
92
115
  if (showTotalSize) {
93
116
  bundleInfo.push([]);
94
- bundleInfo.push([' ', 'Initial Total', formatSize(initialTotalSize)].map(bold));
117
+ const totalSizeElements = [' ', 'Initial Total', formatSize(initialTotalRawSize)];
118
+ if (showEstimatedTransferSize) {
119
+ totalSizeElements.push(typeof initialTotalEstimatedTransferSize === 'number'
120
+ ? formatSize(initialTotalEstimatedTransferSize)
121
+ : '-');
122
+ }
123
+ bundleInfo.push(totalSizeElements.map(bold));
95
124
  }
96
125
  }
97
126
  // Seperator
@@ -100,12 +129,12 @@ function generateBuildStatsTable(data, colors, showTotalSize) {
100
129
  }
101
130
  // Lazy chunks
102
131
  if (changedLazyChunksStats.length) {
103
- bundleInfo.push(['Lazy Chunk Files', 'Names', 'Size'].map(bold), ...changedLazyChunksStats);
132
+ bundleInfo.push(['Lazy Chunk Files', ...baseTitles].map(bold), ...changedLazyChunksStats);
104
133
  }
105
134
  return (0, text_table_1.default)(bundleInfo, {
106
135
  hsep: dim(' | '),
107
136
  stringLength: (s) => (0, color_1.removeColor)(s).length,
108
- align: ['l', 'l', 'r'],
137
+ align: tableAlign,
109
138
  });
110
139
  }
111
140
  function generateBuildStats(hash, time, colors) {
@@ -127,6 +156,7 @@ statsConfig, bundleState) {
127
156
  const rs = (x) => (colors ? color_1.colors.reset(x) : x);
128
157
  const changedChunksStats = bundleState !== null && bundleState !== void 0 ? bundleState : [];
129
158
  let unchangedChunkNumber = 0;
159
+ let hasEstimatedTransferSizes = false;
130
160
  if (!(bundleState === null || bundleState === void 0 ? void 0 : bundleState.length)) {
131
161
  const isFirstRun = !runsCache.has(json.outputPath || '');
132
162
  for (const chunk of json.chunks) {
@@ -136,8 +166,24 @@ statsConfig, bundleState) {
136
166
  continue;
137
167
  }
138
168
  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); });
139
- const summedSize = assets === null || assets === void 0 ? void 0 : assets.filter((asset) => !asset.name.endsWith('.map')).reduce((total, asset) => total + asset.size, 0);
140
- changedChunksStats.push(generateBundleStats({ ...chunk, size: summedSize }));
169
+ let rawSize = 0;
170
+ let estimatedTransferSize;
171
+ if (assets) {
172
+ for (const asset of assets) {
173
+ if (asset.name.endsWith('.map')) {
174
+ continue;
175
+ }
176
+ rawSize += asset.size;
177
+ if (typeof asset.info.estimatedTransferSize === 'number') {
178
+ if (estimatedTransferSize === undefined) {
179
+ estimatedTransferSize = 0;
180
+ hasEstimatedTransferSizes = true;
181
+ }
182
+ estimatedTransferSize += asset.info.estimatedTransferSize;
183
+ }
184
+ }
185
+ }
186
+ changedChunksStats.push(generateBundleStats({ ...chunk, rawSize, estimatedTransferSize }));
141
187
  }
142
188
  unchangedChunkNumber = json.chunks.length - changedChunksStats.length;
143
189
  runsCache.add(json.outputPath || '');
@@ -152,7 +198,7 @@ statsConfig, bundleState) {
152
198
  }
153
199
  return 0;
154
200
  });
155
- const statsTable = generateBuildStatsTable(changedChunksStats, colors, unchangedChunkNumber === 0);
201
+ const statsTable = generateBuildStatsTable(changedChunksStats, colors, unchangedChunkNumber === 0, hasEstimatedTransferSizes);
156
202
  // In some cases we do things outside of webpack context
157
203
  // Such us index generation, service worker augmentation etc...
158
204
  // This will correct the time and include these.