@angular-devkit/build-angular 12.2.3 → 12.2.7

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.
@@ -0,0 +1,16 @@
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
+
9
+ // If the platform does not support the native variant of esbuild, this will crash.
10
+ // This script can then be spawned by the CLI to determine if native usage is supported.
11
+ require('esbuild')
12
+ .formatMessages([], { kind: 'error ' })
13
+ .then(
14
+ () => {},
15
+ () => {},
16
+ );
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@angular-devkit/build-angular",
3
- "version": "12.2.3",
3
+ "version": "12.2.7",
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.1202.3",
11
- "@angular-devkit/build-optimizer": "0.1202.3",
12
- "@angular-devkit/build-webpack": "0.1202.3",
13
- "@angular-devkit/core": "12.2.3",
10
+ "@angular-devkit/architect": "0.1202.7",
11
+ "@angular-devkit/build-optimizer": "0.1202.7",
12
+ "@angular-devkit/build-webpack": "0.1202.7",
13
+ "@angular-devkit/core": "12.2.7",
14
14
  "@babel/core": "7.14.8",
15
15
  "@babel/generator": "7.14.8",
16
16
  "@babel/helper-annotate-as-pure": "7.14.5",
@@ -22,7 +22,7 @@
22
22
  "@babel/template": "7.14.5",
23
23
  "@discoveryjs/json-ext": "0.5.3",
24
24
  "@jsdevtools/coverage-istanbul-loader": "3.0.5",
25
- "@ngtools/webpack": "12.2.3",
25
+ "@ngtools/webpack": "12.2.7",
26
26
  "ansi-colors": "4.1.1",
27
27
  "babel-loader": "8.2.2",
28
28
  "browserslist": "^4.9.1",
@@ -34,7 +34,7 @@
34
34
  "critters": "0.0.10",
35
35
  "css-loader": "6.2.0",
36
36
  "css-minimizer-webpack-plugin": "3.0.2",
37
- "esbuild": "0.12.17",
37
+ "esbuild-wasm": "0.12.29",
38
38
  "find-cache-dir": "3.3.1",
39
39
  "glob": "7.1.7",
40
40
  "https-proxy-agent": "5.0.0",
@@ -44,7 +44,7 @@
44
44
  "less-loader": "10.0.1",
45
45
  "license-webpack-plugin": "2.3.20",
46
46
  "loader-utils": "2.0.0",
47
- "mini-css-extract-plugin": "2.1.0",
47
+ "mini-css-extract-plugin": "2.2.1",
48
48
  "minimatch": "3.0.4",
49
49
  "open": "8.2.1",
50
50
  "ora": "5.4.1",
@@ -76,6 +76,9 @@
76
76
  "webpack-merge": "5.8.0",
77
77
  "webpack-subresource-integrity": "1.5.2"
78
78
  },
79
+ "optionalDependencies": {
80
+ "esbuild": "0.12.29"
81
+ },
79
82
  "peerDependencies": {
80
83
  "@angular/compiler-cli": "^12.0.0",
81
84
  "@angular/localize": "^12.0.0",
@@ -29,7 +29,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.colors = exports.removeColor = void 0;
30
30
  const ansiColors = __importStar(require("ansi-colors"));
31
31
  const tty_1 = require("tty");
32
- const supportsColor = process.stdout instanceof tty_1.WriteStream && process.stdout.getColorDepth() > 1;
32
+ function supportColor() {
33
+ if (process.env.FORCE_COLOR !== undefined) {
34
+ // 2 colors: FORCE_COLOR = 0 (Disables colors), depth 1
35
+ // 16 colors: FORCE_COLOR = 1, depth 4
36
+ // 256 colors: FORCE_COLOR = 2, depth 8
37
+ // 16,777,216 colors: FORCE_COLOR = 3, depth 16
38
+ // See: https://nodejs.org/dist/latest-v12.x/docs/api/tty.html#tty_writestream_getcolordepth_env
39
+ // and https://github.com/nodejs/node/blob/b9f36062d7b5c5039498e98d2f2c180dca2a7065/lib/internal/tty.js#L106;
40
+ switch (process.env.FORCE_COLOR) {
41
+ case '':
42
+ case 'true':
43
+ case '1':
44
+ case '2':
45
+ case '3':
46
+ return true;
47
+ default:
48
+ return false;
49
+ }
50
+ }
51
+ if (process.stdout instanceof tty_1.WriteStream) {
52
+ return process.stdout.getColorDepth() > 1;
53
+ }
54
+ return false;
55
+ }
33
56
  function removeColor(text) {
34
57
  // This has been created because when colors.enabled is false unstyle doesn't work
35
58
  // see: https://github.com/doowb/ansi-colors/blob/a4794363369d7b4d1872d248fc43a12761640d8e/index.js#L38
@@ -40,4 +63,4 @@ exports.removeColor = removeColor;
40
63
  // Create function is not defined in the typings. See: https://github.com/doowb/ansi-colors/pull/44
41
64
  const colors = ansiColors.create();
42
65
  exports.colors = colors;
43
- colors.enabled = supportsColor;
66
+ colors.enabled = supportColor();
@@ -98,7 +98,7 @@ function getDevServerConfig(wco) {
98
98
  },
99
99
  sockPath: path_1.posix.join(servePath, 'sockjs-node'),
100
100
  stats: false,
101
- compress: stylesOptimization.minify || scriptsOptimization,
101
+ compress: false,
102
102
  watchOptions: helpers_1.getWatchOptions(poll),
103
103
  https: getSslConfig(root, wco.buildOptions),
104
104
  overlay: {
@@ -33,6 +33,7 @@ const sass_service_1 = require("../../sass/sass-service");
33
33
  const build_browser_features_1 = require("../../utils/build-browser-features");
34
34
  const environment_options_1 = require("../../utils/environment-options");
35
35
  const plugins_1 = require("../plugins");
36
+ const esbuild_executor_1 = require("../plugins/esbuild-executor");
36
37
  const helpers_1 = require("../utils/helpers");
37
38
  function resolveGlobalStyles(styleEntrypoints, root, preserveSymlinks) {
38
39
  const entryPoints = {};
@@ -243,7 +244,7 @@ function getStylesConfig(wco) {
243
244
  const extraMinimizers = [];
244
245
  if (buildOptions.optimization.styles.minify) {
245
246
  const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
246
- const esbuild = require('esbuild');
247
+ const esbuild = new esbuild_executor_1.EsbuildExecutor();
247
248
  const cssnanoOptions = {
248
249
  preset: [
249
250
  'default',
@@ -439,11 +440,23 @@ function transformSupportedBrowsersToTargets(supportedBrowsers) {
439
440
  // https://esbuild.github.io/api/#target
440
441
  const esBuildSupportedBrowsers = new Set(['safari', 'firefox', 'edge', 'chrome', 'ios']);
441
442
  for (const browser of supportedBrowsers) {
442
- const [browserName, version] = browser.split(' ');
443
+ let [browserName, version] = browser.split(' ');
444
+ // browserslist uses the name `ios_saf` for iOS Safari whereas esbuild uses `ios`
445
+ if (browserName === 'ios_saf') {
446
+ browserName = 'ios';
447
+ // browserslist also uses ranges for iOS Safari versions but only the lowest is required
448
+ // to perform minimum supported feature checks. esbuild also expects a single version.
449
+ [version] = version.split('-');
450
+ }
443
451
  if (browserName === 'ie') {
444
452
  transformed.push('edge12');
445
453
  }
446
454
  else if (esBuildSupportedBrowsers.has(browserName)) {
455
+ if (browserName === 'safari' && version === 'TP') {
456
+ // esbuild only supports numeric versions so `TP` is converted to a high number (999) since
457
+ // a Technology Preview (TP) of Safari is assumed to support all currently known features.
458
+ version = '999';
459
+ }
447
460
  transformed.push(browserName + version);
448
461
  }
449
462
  }
@@ -0,0 +1,46 @@
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 { FormatMessagesOptions, PartialMessage, TransformOptions, TransformResult } from 'esbuild';
9
+ /**
10
+ * Provides the ability to execute esbuild regardless of the current platform's support
11
+ * for using the native variant of esbuild. The native variant will be preferred (assuming
12
+ * the `alwaysUseWasm` constructor option is `false) due to its inherent performance advantages.
13
+ * At first use of esbuild, a supportability test will be automatically performed and the
14
+ * WASM-variant will be used if needed by the platform.
15
+ */
16
+ export declare class EsbuildExecutor implements Pick<typeof import('esbuild'), 'transform' | 'formatMessages'> {
17
+ private alwaysUseWasm;
18
+ private esbuildTransform;
19
+ private esbuildFormatMessages;
20
+ private initialized;
21
+ /**
22
+ * Constructs an instance of the `EsbuildExecutor` class.
23
+ *
24
+ * @param alwaysUseWasm If true, the WASM-variant will be preferred and no support test will be
25
+ * performed; if false (default), the native variant will be preferred.
26
+ */
27
+ constructor(alwaysUseWasm?: boolean);
28
+ /**
29
+ * Determines whether the native variant of esbuild can be used on the current platform.
30
+ *
31
+ * @returns True, if the native variant of esbuild is support; False, if the WASM variant is required.
32
+ */
33
+ static hasNativeSupport(): boolean;
34
+ /**
35
+ * Initializes the esbuild transform and format messages functions.
36
+ *
37
+ * @returns A promise that fulfills when esbuild has been loaded and available for use.
38
+ */
39
+ private ensureEsbuild;
40
+ /**
41
+ * Transitions an executor instance to use the WASM-variant of esbuild.
42
+ */
43
+ private useWasm;
44
+ transform(input: string, options?: TransformOptions): Promise<TransformResult>;
45
+ formatMessages(messages: PartialMessage[], options: FormatMessagesOptions): Promise<string[]>;
46
+ }
@@ -0,0 +1,126 @@
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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || function (mod) {
22
+ if (mod && mod.__esModule) return mod;
23
+ var result = {};
24
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
+ __setModuleDefault(result, mod);
26
+ return result;
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.EsbuildExecutor = void 0;
30
+ const child_process_1 = require("child_process");
31
+ const path = __importStar(require("path"));
32
+ /**
33
+ * Provides the ability to execute esbuild regardless of the current platform's support
34
+ * for using the native variant of esbuild. The native variant will be preferred (assuming
35
+ * the `alwaysUseWasm` constructor option is `false) due to its inherent performance advantages.
36
+ * At first use of esbuild, a supportability test will be automatically performed and the
37
+ * WASM-variant will be used if needed by the platform.
38
+ */
39
+ class EsbuildExecutor {
40
+ /**
41
+ * Constructs an instance of the `EsbuildExecutor` class.
42
+ *
43
+ * @param alwaysUseWasm If true, the WASM-variant will be preferred and no support test will be
44
+ * performed; if false (default), the native variant will be preferred.
45
+ */
46
+ constructor(alwaysUseWasm = false) {
47
+ this.alwaysUseWasm = alwaysUseWasm;
48
+ this.initialized = false;
49
+ this.esbuildTransform = this.esbuildFormatMessages = () => {
50
+ throw new Error('esbuild implementation missing');
51
+ };
52
+ }
53
+ /**
54
+ * Determines whether the native variant of esbuild can be used on the current platform.
55
+ *
56
+ * @returns True, if the native variant of esbuild is support; False, if the WASM variant is required.
57
+ */
58
+ static hasNativeSupport() {
59
+ // Try to use native variant to ensure it is functional for the platform.
60
+ // Spawning a separate esbuild check process is used to determine if the native
61
+ // variant is viable. If check fails, the WASM variant is initialized instead.
62
+ // Attempting to call one of the native esbuild functions is not a viable test
63
+ // currently since esbuild spawn errors are currently not propagated through the
64
+ // call stack for the esbuild function. If this limitation is removed in the future
65
+ // then the separate process spawn check can be removed in favor of a direct function
66
+ // call check.
67
+ try {
68
+ const { status, error } = child_process_1.spawnSync(process.execPath, [
69
+ path.join(__dirname, '../../../esbuild-check.js'),
70
+ ]);
71
+ return status === 0 && error === undefined;
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
77
+ /**
78
+ * Initializes the esbuild transform and format messages functions.
79
+ *
80
+ * @returns A promise that fulfills when esbuild has been loaded and available for use.
81
+ */
82
+ async ensureEsbuild() {
83
+ if (this.initialized) {
84
+ return;
85
+ }
86
+ // If the WASM variant was preferred at class construction or native is not supported, use WASM
87
+ if (this.alwaysUseWasm || !EsbuildExecutor.hasNativeSupport()) {
88
+ await this.useWasm();
89
+ this.initialized = true;
90
+ return;
91
+ }
92
+ try {
93
+ // Use the faster native variant if available.
94
+ const { transform, formatMessages } = await Promise.resolve().then(() => __importStar(require('esbuild')));
95
+ this.esbuildTransform = transform;
96
+ this.esbuildFormatMessages = formatMessages;
97
+ }
98
+ catch {
99
+ // If the native variant is not installed then use the WASM-based variant
100
+ await this.useWasm();
101
+ }
102
+ this.initialized = true;
103
+ }
104
+ /**
105
+ * Transitions an executor instance to use the WASM-variant of esbuild.
106
+ */
107
+ async useWasm() {
108
+ const { transform, formatMessages } = await Promise.resolve().then(() => __importStar(require('esbuild-wasm')));
109
+ this.esbuildTransform = transform;
110
+ this.esbuildFormatMessages = formatMessages;
111
+ // The ESBUILD_BINARY_PATH environment variable cannot exist when attempting to use the
112
+ // WASM variant. If it is then the binary located at the specified path will be used instead
113
+ // of the WASM variant.
114
+ delete process.env.ESBUILD_BINARY_PATH;
115
+ this.alwaysUseWasm = true;
116
+ }
117
+ async transform(input, options) {
118
+ await this.ensureEsbuild();
119
+ return this.esbuildTransform(input, options);
120
+ }
121
+ async formatMessages(messages, options) {
122
+ await this.ensureEsbuild();
123
+ return this.esbuildFormatMessages(messages, options);
124
+ }
125
+ }
126
+ exports.EsbuildExecutor = EsbuildExecutor;
@@ -14,6 +14,7 @@ exports.JavaScriptOptimizerPlugin = void 0;
14
14
  const piscina_1 = __importDefault(require("piscina"));
15
15
  const typescript_1 = require("typescript");
16
16
  const environment_options_1 = require("../../utils/environment-options");
17
+ const esbuild_executor_1 = require("./esbuild-executor");
17
18
  /**
18
19
  * The maximum number of Workers that will be created to execute optimize tasks.
19
20
  */
@@ -105,6 +106,10 @@ class JavaScriptOptimizerPlugin {
105
106
  target,
106
107
  removeLicenses: this.options.removeLicenses,
107
108
  advanced: this.options.advanced,
109
+ // Perform a single native esbuild support check.
110
+ // This removes the need for each worker to perform the check which would
111
+ // otherwise require spawning a separate process per worker.
112
+ alwaysUseWasm: !esbuild_executor_1.EsbuildExecutor.hasNativeSupport(),
108
113
  };
109
114
  // Sort scripts so larger scripts start first - worker pool uses a FIFO queue
110
115
  scriptsToOptimize.sort((a, b) => a.code.length - b.code.length);
@@ -13,22 +13,64 @@ interface OptimizeRequest {
13
13
  * The options to use when optimizing.
14
14
  */
15
15
  options: {
16
+ /**
17
+ * Controls advanced optimizations.
18
+ * Currently these are only terser related:
19
+ * * terser compress passes are set to 2
20
+ * * terser pure_getters option is enabled
21
+ */
16
22
  advanced: boolean;
23
+ /**
24
+ * Specifies the string tokens that should be replaced with a defined value.
25
+ */
17
26
  define?: Record<string, string>;
27
+ /**
28
+ * Controls whether class, function, and variable names should be left intact
29
+ * throughout the output code.
30
+ */
18
31
  keepNames: boolean;
32
+ /**
33
+ * Controls whether license text is removed from the output code.
34
+ * Within the CLI, this option is linked to the license extraction functionality.
35
+ */
19
36
  removeLicenses: boolean;
37
+ /**
38
+ * Controls whether source maps should be generated.
39
+ */
20
40
  sourcemap: boolean;
41
+ /**
42
+ * Specifies the target ECMAScript version for the output code.
43
+ */
21
44
  target: 5 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020;
45
+ /**
46
+ * Controls whether esbuild should only use the WASM-variant instead of trying to
47
+ * use the native variant. Some platforms may not support the native-variant and
48
+ * this option allows one support test to be conducted prior to all the workers starting.
49
+ */
50
+ alwaysUseWasm: boolean;
22
51
  };
23
52
  /**
24
53
  * The JavaScript asset to optimize.
25
54
  */
26
55
  asset: {
56
+ /**
57
+ * The name of the JavaScript asset (typically the filename).
58
+ */
27
59
  name: string;
60
+ /**
61
+ * The source content of the JavaScript asset.
62
+ */
28
63
  code: string;
64
+ /**
65
+ * The source map of the JavaScript asset, if available.
66
+ * This map is merged with all intermediate source maps during optimization.
67
+ */
29
68
  map: object;
30
69
  };
31
70
  }
71
+ /**
72
+ * Handles optimization requests sent from the main thread via the `JavaScriptOptimizerPlugin`.
73
+ */
32
74
  export default function ({ asset, options }: OptimizeRequest): Promise<{
33
75
  name: string;
34
76
  code: string;
@@ -11,23 +11,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
11
11
  };
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  const remapping_1 = __importDefault(require("@ampproject/remapping"));
14
- const esbuild_1 = require("esbuild");
15
14
  const terser_1 = require("terser");
15
+ const esbuild_executor_1 = require("./esbuild-executor");
16
+ /**
17
+ * The cached esbuild executor.
18
+ * This will automatically use the native or WASM version based on platform and availability
19
+ * with the native version given priority due to its superior performance.
20
+ */
21
+ let esbuild;
22
+ /**
23
+ * Handles optimization requests sent from the main thread via the `JavaScriptOptimizerPlugin`.
24
+ */
16
25
  async function default_1({ asset, options }) {
17
26
  // esbuild is used as a first pass
18
- const esbuildResult = await esbuild_1.transform(asset.code, {
19
- minifyIdentifiers: !options.keepNames,
20
- minifySyntax: true,
21
- // NOTE: Disabling whitespace ensures unused pure annotations are kept
22
- minifyWhitespace: false,
23
- pure: ['forwardRef'],
24
- legalComments: options.removeLicenses ? 'none' : 'inline',
25
- sourcefile: asset.name,
26
- sourcemap: options.sourcemap && 'external',
27
- define: options.define,
28
- keepNames: options.keepNames,
29
- target: `es${options.target}`,
30
- });
27
+ const esbuildResult = await optimizeWithEsbuild(asset.code, asset.name, options);
31
28
  // terser is used as a second pass
32
29
  const terserResult = await optimizeWithTerser(asset.name, esbuildResult.code, options.sourcemap, options.target, options.advanced);
33
30
  // Merge intermediate sourcemaps with input sourcemap if enabled
@@ -48,6 +45,65 @@ async function default_1({ asset, options }) {
48
45
  return { name: asset.name, code: terserResult.code, map: fullSourcemap };
49
46
  }
50
47
  exports.default = default_1;
48
+ /**
49
+ * Optimizes a JavaScript asset using esbuild.
50
+ *
51
+ * @param content The JavaScript asset source content to optimize.
52
+ * @param name The name of the JavaScript asset. Used to generate source maps.
53
+ * @param options The optimization request options to apply to the content.
54
+ * @returns A promise that resolves with the optimized code, source map, and any warnings.
55
+ */
56
+ async function optimizeWithEsbuild(content, name, options) {
57
+ var _a;
58
+ if (!esbuild) {
59
+ esbuild = new esbuild_executor_1.EsbuildExecutor(options.alwaysUseWasm);
60
+ }
61
+ let result;
62
+ try {
63
+ result = await esbuild.transform(content, {
64
+ minifyIdentifiers: !options.keepNames,
65
+ minifySyntax: true,
66
+ // NOTE: Disabling whitespace ensures unused pure annotations are kept
67
+ minifyWhitespace: false,
68
+ pure: ['forwardRef'],
69
+ legalComments: options.removeLicenses ? 'none' : 'inline',
70
+ sourcefile: name,
71
+ sourcemap: options.sourcemap && 'external',
72
+ define: options.define,
73
+ keepNames: options.keepNames,
74
+ target: `es${options.target}`,
75
+ });
76
+ }
77
+ catch (error) {
78
+ const failure = error;
79
+ // If esbuild fails with only ES5 support errors, fallback to just terser.
80
+ // This will only happen if ES5 is the output target and a global script contains ES2015+ syntax.
81
+ // In that case, the global script is technically already invalid for the target environment but
82
+ // this is and has been considered a configuration issue. Global scripts must be compatible with
83
+ // the target environment.
84
+ if ((_a = failure.errors) === null || _a === void 0 ? void 0 : _a.every((error) => error.text.includes('to the configured target environment ("es5") is not supported yet'))) {
85
+ result = {
86
+ code: content,
87
+ map: '',
88
+ warnings: [],
89
+ };
90
+ }
91
+ else {
92
+ throw error;
93
+ }
94
+ }
95
+ return result;
96
+ }
97
+ /**
98
+ * Optimizes a JavaScript asset using terser.
99
+ *
100
+ * @param name The name of the JavaScript asset. Used to generate source maps.
101
+ * @param code The JavaScript asset source content to optimize.
102
+ * @param sourcemaps If true, generate an output source map for the optimized code.
103
+ * @param target Specifies the target ECMAScript version for the output code.
104
+ * @param advanced Controls advanced optimizations.
105
+ * @returns A promise that resolves with the optimized code and source map.
106
+ */
51
107
  async function optimizeWithTerser(name, code, sourcemaps, target, advanced) {
52
108
  const result = await terser_1.minify({ [name]: code }, {
53
109
  compress: {