@angular-devkit/build-angular 17.2.0-next.0 → 17.2.0-rc.0
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 +24 -25
- package/src/builders/application/build-action.d.ts +1 -0
- package/src/builders/application/build-action.js +18 -18
- package/src/builders/application/execute-build.js +8 -15
- package/src/builders/application/index.js +20 -3
- package/src/builders/application/options.d.ts +13 -2
- package/src/builders/application/options.js +16 -3
- package/src/builders/application/schema.d.ts +13 -0
- package/src/builders/application/schema.json +12 -0
- package/src/builders/application/setup-bundling.js +2 -2
- package/src/builders/browser/index.js +3 -2
- package/src/builders/dev-server/builder.js +13 -2
- package/src/builders/dev-server/options.d.ts +1 -0
- package/src/builders/dev-server/options.js +3 -1
- package/src/builders/dev-server/schema.d.ts +19 -0
- package/src/builders/dev-server/schema.json +18 -0
- package/src/builders/dev-server/vite-server.js +6 -6
- package/src/builders/extract-i18n/application-extraction.js +3 -1
- package/src/builders/server/index.js +3 -2
- package/src/tools/babel/plugins/elide-angular-metadata.d.ts +1 -1
- package/src/tools/babel/plugins/elide-angular-metadata.js +38 -30
- package/src/tools/babel/plugins/pure-toplevel-functions.d.ts +1 -1
- package/src/tools/babel/plugins/pure-toplevel-functions.js +3 -4
- package/src/tools/esbuild/angular/compiler-plugin.js +1 -1
- package/src/tools/esbuild/application-code-bundle.js +7 -4
- package/src/tools/esbuild/budget-stats.js +5 -0
- package/src/tools/esbuild/bundler-context.d.ts +1 -0
- package/src/tools/esbuild/bundler-context.js +19 -5
- package/src/tools/esbuild/bundler-execution-result.d.ts +2 -0
- package/src/tools/esbuild/bundler-execution-result.js +6 -0
- package/src/tools/esbuild/compiler-plugin-options.js +2 -1
- package/src/tools/esbuild/external-packages-plugin.d.ts +3 -1
- package/src/tools/esbuild/external-packages-plugin.js +9 -5
- package/src/tools/esbuild/global-scripts.js +3 -4
- package/src/tools/esbuild/global-styles.js +2 -1
- package/src/tools/esbuild/index-html-generator.js +4 -2
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
- package/src/tools/esbuild/stylesheets/bundle-options.js +1 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +7 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +24 -8
- package/src/tools/esbuild/utils.d.ts +5 -8
- package/src/tools/esbuild/utils.js +64 -31
- package/src/tools/vite/angular-memory-plugin.js +13 -0
- package/src/tools/webpack/utils/stats.d.ts +1 -0
- package/src/tools/webpack/utils/stats.js +101 -49
- package/src/utils/environment-options.d.ts +1 -0
- package/src/utils/environment-options.js +3 -1
- package/src/utils/load-proxy-config.js +3 -3
- package/src/utils/postcss-configuration.d.ts +11 -0
- package/src/utils/postcss-configuration.js +77 -0
|
@@ -20,9 +20,11 @@ async function extractMessages(options, builderName, context, extractorConstruct
|
|
|
20
20
|
// Setup the build options for the application based on the buildTarget option
|
|
21
21
|
const buildOptions = (await context.validateOptions(await context.getTargetOptions(options.buildTarget), builderName));
|
|
22
22
|
buildOptions.optimization = false;
|
|
23
|
-
buildOptions.sourceMap = { scripts: true, vendor: true };
|
|
23
|
+
buildOptions.sourceMap = { scripts: true, vendor: true, styles: false };
|
|
24
24
|
buildOptions.localize = false;
|
|
25
25
|
buildOptions.budgets = undefined;
|
|
26
|
+
buildOptions.index = false;
|
|
27
|
+
buildOptions.serviceWorker = false;
|
|
26
28
|
let build;
|
|
27
29
|
if (builderName === '@angular-devkit/build-angular:application') {
|
|
28
30
|
build = application_1.buildApplicationInternal;
|
|
@@ -62,8 +62,9 @@ function execute(options, context, transforms = {}) {
|
|
|
62
62
|
return (0, build_webpack_1.runWebpack)(config, context, {
|
|
63
63
|
webpackFactory: require('webpack'),
|
|
64
64
|
logging: (stats, config) => {
|
|
65
|
-
if (options.verbose) {
|
|
66
|
-
|
|
65
|
+
if (options.verbose && config.stats !== false) {
|
|
66
|
+
const statsOptions = config.stats === true ? undefined : config.stats;
|
|
67
|
+
context.logger.info(stats.toString(statsOptions));
|
|
67
68
|
}
|
|
68
69
|
},
|
|
69
70
|
}).pipe((0, rxjs_1.concatMap)(async (output) => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference path="../../../../../../../../../../packages/angular_devkit/build_angular/src/babel-bazel.d.ts" />
|
|
9
9
|
/// <reference types="@angular/compiler-cli/private/babel" />
|
|
10
|
-
import { PluginObj } from '@babel/core';
|
|
10
|
+
import type { PluginObj } from '@babel/core';
|
|
11
11
|
/**
|
|
12
12
|
* Provides one or more keywords that if found within the content of a source file indicate
|
|
13
13
|
* that this plugin should be used with a source file.
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.getKeywords = void 0;
|
|
11
|
-
const core_1 = require("@babel/core");
|
|
12
11
|
/**
|
|
13
12
|
* The name of the Angular class metadata function created by the Angular compiler.
|
|
14
13
|
*/
|
|
@@ -28,9 +27,18 @@ const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
|
|
|
28
27
|
* @returns An a string iterable containing one or more keywords.
|
|
29
28
|
*/
|
|
30
29
|
function getKeywords() {
|
|
31
|
-
return
|
|
30
|
+
return Object.keys(angularMetadataFunctions);
|
|
32
31
|
}
|
|
33
32
|
exports.getKeywords = getKeywords;
|
|
33
|
+
/**
|
|
34
|
+
* An object map of function names and related value checks for discovery of Angular generated
|
|
35
|
+
* metadata calls.
|
|
36
|
+
*/
|
|
37
|
+
const angularMetadataFunctions = {
|
|
38
|
+
[SET_CLASS_METADATA_NAME]: isSetClassMetadataCall,
|
|
39
|
+
[SET_CLASS_METADATA_ASYNC_NAME]: isSetClassMetadataAsyncCall,
|
|
40
|
+
[SET_CLASS_DEBUG_INFO_NAME]: isSetClassDebugInfoCall,
|
|
41
|
+
};
|
|
34
42
|
/**
|
|
35
43
|
* A babel plugin factory function for eliding the Angular class metadata function (`ɵsetClassMetadata`).
|
|
36
44
|
*
|
|
@@ -40,20 +48,23 @@ function default_1() {
|
|
|
40
48
|
return {
|
|
41
49
|
visitor: {
|
|
42
50
|
CallExpression(path) {
|
|
43
|
-
const callee = path.
|
|
44
|
-
const callArguments = path.node.arguments;
|
|
51
|
+
const callee = path.get('callee');
|
|
45
52
|
// The function being called must be the metadata function name
|
|
46
53
|
let calleeName;
|
|
47
|
-
if (
|
|
48
|
-
|
|
54
|
+
if (callee.isMemberExpression()) {
|
|
55
|
+
const calleeProperty = callee.get('property');
|
|
56
|
+
if (calleeProperty.isIdentifier()) {
|
|
57
|
+
calleeName = calleeProperty.node.name;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (callee.isIdentifier()) {
|
|
61
|
+
calleeName = callee.node.name;
|
|
49
62
|
}
|
|
50
|
-
|
|
51
|
-
|
|
63
|
+
if (!calleeName) {
|
|
64
|
+
return;
|
|
52
65
|
}
|
|
53
|
-
if (calleeName
|
|
54
|
-
(
|
|
55
|
-
isRemoveClassmetadataAsyncCall(calleeName, callArguments) ||
|
|
56
|
-
isSetClassDebugInfoCall(calleeName, callArguments))) {
|
|
66
|
+
if (Object.hasOwn(angularMetadataFunctions, calleeName) &&
|
|
67
|
+
angularMetadataFunctions[calleeName](path.get('arguments'))) {
|
|
57
68
|
// The metadata function is always emitted inside a function expression
|
|
58
69
|
const parent = path.getFunctionParent();
|
|
59
70
|
if (parent && (parent.isFunctionExpression() || parent.isArrowFunctionExpression())) {
|
|
@@ -68,35 +79,32 @@ function default_1() {
|
|
|
68
79
|
}
|
|
69
80
|
exports.default = default_1;
|
|
70
81
|
/** Determines if a function call is a call to `setClassMetadata`. */
|
|
71
|
-
function
|
|
82
|
+
function isSetClassMetadataCall(callArguments) {
|
|
72
83
|
// `setClassMetadata` calls have to meet the following criteria:
|
|
73
84
|
// * First must be an identifier
|
|
74
85
|
// * Second must be an array literal
|
|
75
|
-
return (
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
core_1.types.isArrayExpression(args[1]));
|
|
86
|
+
return (callArguments.length === 4 &&
|
|
87
|
+
callArguments[0].isIdentifier() &&
|
|
88
|
+
callArguments[1].isArrayExpression());
|
|
79
89
|
}
|
|
80
90
|
/** Determines if a function call is a call to `setClassMetadataAsync`. */
|
|
81
|
-
function
|
|
91
|
+
function isSetClassMetadataAsyncCall(callArguments) {
|
|
82
92
|
// `setClassMetadataAsync` calls have to meet the following criteria:
|
|
83
93
|
// * First argument must be an identifier.
|
|
84
94
|
// * Second argument must be an inline function.
|
|
85
95
|
// * Third argument must be an inline function.
|
|
86
|
-
return (
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
isInlineFunction(
|
|
90
|
-
isInlineFunction(args[2]));
|
|
96
|
+
return (callArguments.length === 3 &&
|
|
97
|
+
callArguments[0].isIdentifier() &&
|
|
98
|
+
isInlineFunction(callArguments[1]) &&
|
|
99
|
+
isInlineFunction(callArguments[2]));
|
|
91
100
|
}
|
|
92
101
|
/** Determines if a function call is a call to `setClassDebugInfo`. */
|
|
93
|
-
function isSetClassDebugInfoCall(
|
|
94
|
-
return (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
core_1.types.isObjectExpression(args[1]));
|
|
102
|
+
function isSetClassDebugInfoCall(callArguments) {
|
|
103
|
+
return (callArguments.length === 2 &&
|
|
104
|
+
callArguments[0].isIdentifier() &&
|
|
105
|
+
callArguments[1].isObjectExpression());
|
|
98
106
|
}
|
|
99
107
|
/** Determines if a node is an inline function expression. */
|
|
100
|
-
function isInlineFunction(
|
|
101
|
-
return
|
|
108
|
+
function isInlineFunction(path) {
|
|
109
|
+
return path.isFunctionExpression() || path.isArrowFunctionExpression();
|
|
102
110
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/// <reference path="../../../../../../../../../../packages/angular_devkit/build_angular/src/babel-bazel.d.ts" />
|
|
9
9
|
/// <reference types="@angular/compiler-cli/private/babel" />
|
|
10
|
-
import { PluginObj } from '@babel/core';
|
|
10
|
+
import type { PluginObj } from '@babel/core';
|
|
11
11
|
/**
|
|
12
12
|
* A babel plugin factory function for adding the PURE annotation to top-level new and call expressions.
|
|
13
13
|
*
|
|
@@ -33,7 +33,6 @@ 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
|
-
const core_1 = require("@babel/core");
|
|
37
36
|
const helper_annotate_as_pure_1 = __importDefault(require("@babel/helper-annotate-as-pure"));
|
|
38
37
|
const tslib = __importStar(require("tslib"));
|
|
39
38
|
/**
|
|
@@ -67,14 +66,14 @@ function default_1() {
|
|
|
67
66
|
if (path.getFunctionParent()) {
|
|
68
67
|
return;
|
|
69
68
|
}
|
|
70
|
-
const callee = path.
|
|
71
|
-
if ((
|
|
69
|
+
const callee = path.get('callee');
|
|
70
|
+
if ((callee.isFunctionExpression() || callee.isArrowFunctionExpression()) &&
|
|
72
71
|
path.node.arguments.length !== 0) {
|
|
73
72
|
return;
|
|
74
73
|
}
|
|
75
74
|
// Do not annotate TypeScript helpers emitted by the TypeScript compiler.
|
|
76
75
|
// TypeScript helpers are intended to cause side effects.
|
|
77
|
-
if (
|
|
76
|
+
if (callee.isIdentifier() && isTslibHelperName(callee.node.name)) {
|
|
78
77
|
return;
|
|
79
78
|
}
|
|
80
79
|
(0, helper_annotate_as_pure_1.default)(path);
|
|
@@ -162,7 +162,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
162
162
|
});
|
|
163
163
|
referencedFileTracker.add(containingFile, Object.keys(workerResult.metafile.inputs).map((input) => path.join(build.initialOptions.absWorkingDir ?? '', input)));
|
|
164
164
|
// Return bundled worker file entry name to be used in the built output
|
|
165
|
-
const workerCodeFile = workerResult.outputFiles.find((file) =>
|
|
165
|
+
const workerCodeFile = workerResult.outputFiles.find((file) => /^worker-[A-Z0-9]{8}.[cm]?js$/.test(path.basename(file.path)));
|
|
166
166
|
(0, node_assert_1.default)(workerCodeFile, 'Web Worker bundled code file should always be present.');
|
|
167
167
|
const workerCodePath = path.relative(build.initialOptions.outdir ?? '', workerCodeFile.path);
|
|
168
168
|
return workerCodePath.replaceAll('\\', '/');
|
|
@@ -53,9 +53,11 @@ function createBrowserCodeBundleOptions(options, target, sourceFileCache) {
|
|
|
53
53
|
}
|
|
54
54
|
if (options.externalPackages) {
|
|
55
55
|
// Package files affected by a customized loader should not be implicitly marked as external
|
|
56
|
-
if (options.loaderExtensions ||
|
|
56
|
+
if (options.loaderExtensions ||
|
|
57
|
+
options.plugins ||
|
|
58
|
+
typeof options.externalPackages === 'object') {
|
|
57
59
|
// Plugin must be added after custom plugins to ensure any added loader options are considered
|
|
58
|
-
buildOptions.plugins?.push((0, external_packages_plugin_1.createExternalPackagesPlugin)());
|
|
60
|
+
buildOptions.plugins?.push((0, external_packages_plugin_1.createExternalPackagesPlugin)(options.externalPackages !== true ? options.externalPackages : undefined));
|
|
59
61
|
}
|
|
60
62
|
else {
|
|
61
63
|
// Safe to use the packages external option directly
|
|
@@ -230,7 +232,7 @@ function createServerPolyfillBundleOptions(options, target, sourceFileCache) {
|
|
|
230
232
|
}
|
|
231
233
|
exports.createServerPolyfillBundleOptions = createServerPolyfillBundleOptions;
|
|
232
234
|
function getEsBuildCommonOptions(options) {
|
|
233
|
-
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, } = options;
|
|
235
|
+
const { workspaceRoot, outExtension, optimizationOptions, sourcemapOptions, tsconfig, externalDependencies, outputNames, preserveSymlinks, jit, loaderExtensions, jsonLogs, } = options;
|
|
234
236
|
// Ensure unique hashes for i18n translation changes when using post-process inlining.
|
|
235
237
|
// This hash value is added as a footer to each file and ensures that the output file names (with hashes)
|
|
236
238
|
// change when translation files have changed. If this is not done the post processed files may have
|
|
@@ -250,7 +252,7 @@ function getEsBuildCommonOptions(options) {
|
|
|
250
252
|
resolveExtensions: ['.ts', '.tsx', '.mjs', '.js'],
|
|
251
253
|
metafile: true,
|
|
252
254
|
legalComments: options.extractLicenses ? 'none' : 'eof',
|
|
253
|
-
logLevel: options.verbose ? 'debug' : 'silent',
|
|
255
|
+
logLevel: options.verbose && !jsonLogs ? 'debug' : 'silent',
|
|
254
256
|
minifyIdentifiers: optimizationOptions.scripts && environment_options_1.allowMangle,
|
|
255
257
|
minifySyntax: optimizationOptions.scripts,
|
|
256
258
|
minifyWhitespace: optimizationOptions.scripts,
|
|
@@ -265,6 +267,7 @@ function getEsBuildCommonOptions(options) {
|
|
|
265
267
|
write: false,
|
|
266
268
|
preserveSymlinks,
|
|
267
269
|
define: {
|
|
270
|
+
...options.define,
|
|
268
271
|
// Only set to false when script optimizations are enabled. It should not be set to true because
|
|
269
272
|
// Angular turns `ngDevMode` into an object for development debugging purposes when not defined
|
|
270
273
|
// which a constant true value would break.
|
|
@@ -26,6 +26,11 @@ function generateBudgetStats(metafile, initialFiles) {
|
|
|
26
26
|
if (!file.endsWith('.js') && !file.endsWith('.css')) {
|
|
27
27
|
continue;
|
|
28
28
|
}
|
|
29
|
+
// Exclude server bundles
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
if (entry['ng-platform-server']) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
29
34
|
const initialRecord = initialFiles.get(file);
|
|
30
35
|
let name = initialRecord?.name;
|
|
31
36
|
if (name === undefined && entry.entryPoint) {
|
|
@@ -162,6 +162,12 @@ class BundlerContext {
|
|
|
162
162
|
// For non-incremental builds, perform a single build
|
|
163
163
|
result = await (0, esbuild_1.build)(this.#esbuildOptions);
|
|
164
164
|
}
|
|
165
|
+
if (this.#platformIsServer) {
|
|
166
|
+
for (const entry of Object.values(result.metafile.outputs)) {
|
|
167
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
168
|
+
entry['ng-platform-server'] = true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
165
171
|
}
|
|
166
172
|
catch (failure) {
|
|
167
173
|
// Build failures will throw an exception which contains errors/warnings
|
|
@@ -226,6 +232,7 @@ class BundlerContext {
|
|
|
226
232
|
name,
|
|
227
233
|
type,
|
|
228
234
|
entrypoint: true,
|
|
235
|
+
serverFile: this.#platformIsServer,
|
|
229
236
|
};
|
|
230
237
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
231
238
|
initialFiles.set(relativeFilePath, record);
|
|
@@ -245,6 +252,7 @@ class BundlerContext {
|
|
|
245
252
|
type: initialImport.kind === 'import-rule' ? 'style' : 'script',
|
|
246
253
|
entrypoint: false,
|
|
247
254
|
external: initialImport.external,
|
|
255
|
+
serverFile: this.#platformIsServer,
|
|
248
256
|
};
|
|
249
257
|
if (!this.initialFilter || this.initialFilter(record)) {
|
|
250
258
|
initialFiles.set(initialImport.path, record);
|
|
@@ -260,15 +268,16 @@ class BundlerContext {
|
|
|
260
268
|
for (const { imports } of Object.values(result.metafile.outputs)) {
|
|
261
269
|
for (const importData of imports) {
|
|
262
270
|
if (!importData.external ||
|
|
263
|
-
(importData.kind !== 'import-statement' &&
|
|
271
|
+
(importData.kind !== 'import-statement' &&
|
|
272
|
+
importData.kind !== 'dynamic-import' &&
|
|
273
|
+
importData.kind !== 'require-call')) {
|
|
264
274
|
continue;
|
|
265
275
|
}
|
|
266
276
|
externalImports.add(importData.path);
|
|
267
277
|
}
|
|
268
278
|
}
|
|
269
279
|
(0, node_assert_1.default)(this.#esbuildOptions, 'esbuild options cannot be undefined.');
|
|
270
|
-
const {
|
|
271
|
-
const platformIsServer = platform === 'node';
|
|
280
|
+
const { assetNames = '' } = this.#esbuildOptions;
|
|
272
281
|
const mediaDirname = (0, node_path_1.dirname)(assetNames);
|
|
273
282
|
const outputFiles = result.outputFiles.map((file) => {
|
|
274
283
|
let fileType;
|
|
@@ -276,7 +285,9 @@ class BundlerContext {
|
|
|
276
285
|
fileType = BuildOutputFileType.Media;
|
|
277
286
|
}
|
|
278
287
|
else {
|
|
279
|
-
fileType = platformIsServer
|
|
288
|
+
fileType = this.#platformIsServer
|
|
289
|
+
? BuildOutputFileType.Server
|
|
290
|
+
: BuildOutputFileType.Browser;
|
|
280
291
|
}
|
|
281
292
|
return (0, utils_1.convertOutputFile)(file, fileType);
|
|
282
293
|
});
|
|
@@ -286,7 +297,7 @@ class BundlerContext {
|
|
|
286
297
|
outputFiles,
|
|
287
298
|
initialFiles,
|
|
288
299
|
externalImports: {
|
|
289
|
-
[platformIsServer ? 'server' : 'browser']: externalImports,
|
|
300
|
+
[this.#platformIsServer ? 'server' : 'browser']: externalImports,
|
|
290
301
|
},
|
|
291
302
|
externalConfiguration: this.#esbuildOptions.external,
|
|
292
303
|
errors: undefined,
|
|
@@ -306,6 +317,9 @@ class BundlerContext {
|
|
|
306
317
|
}
|
|
307
318
|
}
|
|
308
319
|
}
|
|
320
|
+
get #platformIsServer() {
|
|
321
|
+
return this.#esbuildOptions?.platform === 'node';
|
|
322
|
+
}
|
|
309
323
|
/**
|
|
310
324
|
* Invalidate a stored bundler result based on the previous watch files
|
|
311
325
|
* and a list of changed files.
|
|
@@ -33,6 +33,7 @@ export declare class ExecutionResult {
|
|
|
33
33
|
outputFiles: BuildOutputFile[];
|
|
34
34
|
assetFiles: BuildOutputAsset[];
|
|
35
35
|
errors: (Message | PartialMessage)[];
|
|
36
|
+
prerenderedRoutes: string[];
|
|
36
37
|
warnings: (Message | PartialMessage)[];
|
|
37
38
|
externalMetadata?: ExternalResultMetadata;
|
|
38
39
|
constructor(rebuildContexts: BundlerContext[], codeBundleCache?: SourceFileCache | undefined);
|
|
@@ -40,6 +41,7 @@ export declare class ExecutionResult {
|
|
|
40
41
|
addAssets(assets: BuildOutputAsset[]): void;
|
|
41
42
|
addError(error: PartialMessage | string): void;
|
|
42
43
|
addErrors(errors: (PartialMessage | string)[]): void;
|
|
44
|
+
addPrerenderedRoutes(routes: string[]): void;
|
|
43
45
|
addWarning(error: PartialMessage | string): void;
|
|
44
46
|
addWarnings(errors: (PartialMessage | string)[]): void;
|
|
45
47
|
/**
|
|
@@ -19,6 +19,7 @@ class ExecutionResult {
|
|
|
19
19
|
outputFiles = [];
|
|
20
20
|
assetFiles = [];
|
|
21
21
|
errors = [];
|
|
22
|
+
prerenderedRoutes = [];
|
|
22
23
|
warnings = [];
|
|
23
24
|
externalMetadata;
|
|
24
25
|
constructor(rebuildContexts, codeBundleCache) {
|
|
@@ -44,6 +45,11 @@ class ExecutionResult {
|
|
|
44
45
|
this.addError(error);
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
addPrerenderedRoutes(routes) {
|
|
49
|
+
this.prerenderedRoutes.push(...routes);
|
|
50
|
+
// Sort the prerendered routes.
|
|
51
|
+
this.prerenderedRoutes.sort((a, b) => a.localeCompare(b));
|
|
52
|
+
}
|
|
47
53
|
addWarning(error) {
|
|
48
54
|
if (typeof error === 'string') {
|
|
49
55
|
this.warnings.push({ text: error, location: null });
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.createCompilerPluginOptions = void 0;
|
|
11
11
|
function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
12
|
-
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, publicPath, } = options;
|
|
12
|
+
const { workspaceRoot, optimizationOptions, sourcemapOptions, tsconfig, outputNames, fileReplacements, externalDependencies, preserveSymlinks, stylePreprocessorOptions, advancedOptimizations, inlineStyleLanguage, jit, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, } = options;
|
|
13
13
|
return {
|
|
14
14
|
// JS/TS options
|
|
15
15
|
pluginOptions: {
|
|
@@ -40,6 +40,7 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
|
|
|
40
40
|
inlineStyleLanguage,
|
|
41
41
|
preserveSymlinks,
|
|
42
42
|
tailwindConfiguration,
|
|
43
|
+
postcssConfiguration,
|
|
43
44
|
cacheOptions,
|
|
44
45
|
publicPath,
|
|
45
46
|
},
|
|
@@ -17,22 +17,26 @@ const EXTERNAL_PACKAGE_RESOLUTION = Symbol('EXTERNAL_PACKAGE_RESOLUTION');
|
|
|
17
17
|
*
|
|
18
18
|
* @returns An esbuild plugin.
|
|
19
19
|
*/
|
|
20
|
-
function createExternalPackagesPlugin() {
|
|
20
|
+
function createExternalPackagesPlugin(options) {
|
|
21
|
+
const exclusions = options?.exclude?.length ? new Set(options.exclude) : undefined;
|
|
21
22
|
return {
|
|
22
23
|
name: 'angular-external-packages',
|
|
23
24
|
setup(build) {
|
|
24
|
-
|
|
25
|
-
if
|
|
26
|
-
|
|
25
|
+
const loaderOptionKeys = build.initialOptions.loader && Object.keys(build.initialOptions.loader);
|
|
26
|
+
// Safe to use native packages external option if no loader options or exclusions present
|
|
27
|
+
if (!exclusions && !loaderOptionKeys?.length) {
|
|
27
28
|
build.initialOptions.packages = 'external';
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
30
|
-
const loaderFileExtensions = new Set(
|
|
31
|
+
const loaderFileExtensions = new Set(loaderOptionKeys);
|
|
31
32
|
// Only attempt resolve of non-relative and non-absolute paths
|
|
32
33
|
build.onResolve({ filter: /^[^./]/ }, async (args) => {
|
|
33
34
|
if (args.pluginData?.[EXTERNAL_PACKAGE_RESOLUTION]) {
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
37
|
+
if (exclusions?.has(args.path)) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
36
40
|
const { importer, kind, resolveDir, namespace, pluginData = {} } = args;
|
|
37
41
|
pluginData[EXTERNAL_PACKAGE_RESOLUTION] = true;
|
|
38
42
|
const result = await build.resolve(args.path, {
|
|
@@ -49,7 +49,7 @@ const virtual_module_plugin_1 = require("./virtual-module-plugin");
|
|
|
49
49
|
* @returns An esbuild BuildOptions object.
|
|
50
50
|
*/
|
|
51
51
|
function createGlobalScriptsBundleOptions(options, target, initial) {
|
|
52
|
-
const { globalScripts, optimizationOptions, outputNames, preserveSymlinks, sourcemapOptions, workspaceRoot, } = options;
|
|
52
|
+
const { globalScripts, optimizationOptions, outputNames, preserveSymlinks, sourcemapOptions, jsonLogs, workspaceRoot, } = options;
|
|
53
53
|
const namespace = 'angular:script/global';
|
|
54
54
|
const entryPoints = {};
|
|
55
55
|
let found = false;
|
|
@@ -74,7 +74,7 @@ function createGlobalScriptsBundleOptions(options, target, initial) {
|
|
|
74
74
|
mainFields: ['script', 'browser', 'main'],
|
|
75
75
|
conditions: ['script'],
|
|
76
76
|
resolveExtensions: ['.mjs', '.js'],
|
|
77
|
-
logLevel: options.verbose ? 'debug' : 'silent',
|
|
77
|
+
logLevel: options.verbose && !jsonLogs ? 'debug' : 'silent',
|
|
78
78
|
metafile: true,
|
|
79
79
|
minify: optimizationOptions.scripts,
|
|
80
80
|
outdir: workspaceRoot,
|
|
@@ -91,8 +91,7 @@ function createGlobalScriptsBundleOptions(options, target, initial) {
|
|
|
91
91
|
// Add the `js` extension here so that esbuild generates an output file with the extension
|
|
92
92
|
transformPath: (path) => path.slice(namespace.length + 1) + '.js',
|
|
93
93
|
loadContent: (args, build) => (0, load_result_cache_1.createCachedLoad)(loadCache, async (args) => {
|
|
94
|
-
const files = globalScripts.find(({ name }) => name === args.path.slice(0, -3))
|
|
95
|
-
?.files;
|
|
94
|
+
const files = globalScripts.find(({ name }) => name === args.path.slice(0, -3))?.files;
|
|
96
95
|
(0, node_assert_1.default)(files, `Invalid operation: global scripts name not found [${args.path}]`);
|
|
97
96
|
// Global scripts are concatenated using magic-string instead of bundled via esbuild.
|
|
98
97
|
const bundleContent = new magic_string_1.Bundle();
|
|
@@ -15,7 +15,7 @@ const node_assert_1 = __importDefault(require("node:assert"));
|
|
|
15
15
|
const bundle_options_1 = require("./stylesheets/bundle-options");
|
|
16
16
|
const virtual_module_plugin_1 = require("./virtual-module-plugin");
|
|
17
17
|
function createGlobalStylesBundleOptions(options, target, initial) {
|
|
18
|
-
const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, cacheOptions, publicPath, } = options;
|
|
18
|
+
const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, globalStyles, preserveSymlinks, externalDependencies, stylePreprocessorOptions, tailwindConfiguration, postcssConfiguration, cacheOptions, publicPath, } = options;
|
|
19
19
|
const namespace = 'angular:styles/global';
|
|
20
20
|
const entryPoints = {};
|
|
21
21
|
let found = false;
|
|
@@ -46,6 +46,7 @@ function createGlobalStylesBundleOptions(options, target, initial) {
|
|
|
46
46
|
},
|
|
47
47
|
includePaths: stylePreprocessorOptions?.includePaths,
|
|
48
48
|
tailwindConfiguration,
|
|
49
|
+
postcssConfiguration,
|
|
49
50
|
cacheOptions,
|
|
50
51
|
publicPath,
|
|
51
52
|
}, loadCache);
|
|
@@ -47,7 +47,7 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
|
|
|
47
47
|
(0, node_assert_1.default)(indexHtmlOptions, 'indexHtmlOptions cannot be undefined.');
|
|
48
48
|
if (!externalPackages && indexHtmlOptions.preloadInitial) {
|
|
49
49
|
for (const [key, value] of initialFiles) {
|
|
50
|
-
if (value.entrypoint) {
|
|
50
|
+
if (value.entrypoint || value.serverFile) {
|
|
51
51
|
// Entry points are already referenced in the HTML
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
@@ -94,7 +94,9 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
|
|
|
94
94
|
baseHref,
|
|
95
95
|
lang,
|
|
96
96
|
outputPath: virtualOutputPath,
|
|
97
|
-
files: [...initialFiles]
|
|
97
|
+
files: [...initialFiles]
|
|
98
|
+
.filter(([, file]) => !file.serverFile)
|
|
99
|
+
.map(([file, record]) => ({
|
|
98
100
|
name: record.name ?? '',
|
|
99
101
|
file,
|
|
100
102
|
extension: node_path_1.default.extname(file),
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { BuildOptions } from 'esbuild';
|
|
9
9
|
import { NormalizedCachedOptions } from '../../../utils/normalize-cache';
|
|
10
|
+
import { PostcssConfiguration } from '../../../utils/postcss-configuration';
|
|
10
11
|
import { LoadResultCache } from '../load-result-cache';
|
|
11
12
|
export interface BundleStylesheetOptions {
|
|
12
13
|
workspaceRoot: string;
|
|
@@ -25,6 +26,7 @@ export interface BundleStylesheetOptions {
|
|
|
25
26
|
file: string;
|
|
26
27
|
package: string;
|
|
27
28
|
};
|
|
29
|
+
postcssConfiguration?: PostcssConfiguration;
|
|
28
30
|
publicPath?: string;
|
|
29
31
|
cacheOptions: NormalizedCachedOptions;
|
|
30
32
|
}
|
|
@@ -26,6 +26,7 @@ function createStylesheetBundleOptions(options, cache, inlineComponentData) {
|
|
|
26
26
|
includePaths,
|
|
27
27
|
inlineComponentData,
|
|
28
28
|
tailwindConfiguration: options.tailwindConfiguration,
|
|
29
|
+
postcssConfiguration: options.postcssConfiguration,
|
|
29
30
|
}, cache);
|
|
30
31
|
const plugins = [
|
|
31
32
|
pluginFactory.create(sass_language_1.SassStylesheetLanguage),
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import type { OnLoadResult, Plugin, PluginBuild } from 'esbuild';
|
|
9
|
+
import type { PostcssConfiguration } from '../../../utils/postcss-configuration';
|
|
9
10
|
import { LoadResultCache } from '../load-result-cache';
|
|
10
11
|
/**
|
|
11
12
|
* An object containing the plugin options to use when processing stylesheets.
|
|
@@ -35,6 +36,12 @@ export interface StylesheetPluginOptions {
|
|
|
35
36
|
file: string;
|
|
36
37
|
package: string;
|
|
37
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Optional configuration object for custom postcss usage. If present, postcss will be
|
|
41
|
+
* initialized and used for every stylesheet. This overrides the tailwind integration
|
|
42
|
+
* and any tailwind usage must be manually configured in the custom postcss usage.
|
|
43
|
+
*/
|
|
44
|
+
postcssConfiguration?: PostcssConfiguration;
|
|
38
45
|
}
|
|
39
46
|
export interface StylesheetLanguage {
|
|
40
47
|
name: string;
|
|
@@ -72,7 +72,9 @@ class StylesheetPluginFactory {
|
|
|
72
72
|
}
|
|
73
73
|
create(language) {
|
|
74
74
|
// Return a noop plugin if no load actions are required
|
|
75
|
-
if (!language.process &&
|
|
75
|
+
if (!language.process &&
|
|
76
|
+
!this.options.postcssConfiguration &&
|
|
77
|
+
!this.options.tailwindConfiguration) {
|
|
76
78
|
return {
|
|
77
79
|
name: 'angular-' + language.name,
|
|
78
80
|
setup() { },
|
|
@@ -84,7 +86,23 @@ class StylesheetPluginFactory {
|
|
|
84
86
|
if (this.postcssProcessor) {
|
|
85
87
|
return this.postcssProcessor;
|
|
86
88
|
}
|
|
87
|
-
if (options.
|
|
89
|
+
if (options.postcssConfiguration) {
|
|
90
|
+
const postCssInstanceKey = JSON.stringify(options.postcssConfiguration);
|
|
91
|
+
this.postcssProcessor = postcssProcessor.get(postCssInstanceKey)?.deref();
|
|
92
|
+
if (!this.postcssProcessor) {
|
|
93
|
+
postcss ??= (await Promise.resolve().then(() => __importStar(require('postcss')))).default;
|
|
94
|
+
this.postcssProcessor = postcss();
|
|
95
|
+
for (const [pluginName, pluginOptions] of options.postcssConfiguration.plugins) {
|
|
96
|
+
const { default: plugin } = await Promise.resolve(`${pluginName}`).then(s => __importStar(require(s)));
|
|
97
|
+
if (typeof plugin !== 'function' || plugin.postcss !== true) {
|
|
98
|
+
throw new Error(`Attempted to load invalid Postcss plugin: "${pluginName}"`);
|
|
99
|
+
}
|
|
100
|
+
this.postcssProcessor.use(plugin(pluginOptions));
|
|
101
|
+
}
|
|
102
|
+
postcssProcessor.set(postCssInstanceKey, new WeakRef(this.postcssProcessor));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (options.tailwindConfiguration) {
|
|
88
106
|
const { package: tailwindPackage, file: config } = options.tailwindConfiguration;
|
|
89
107
|
const postCssInstanceKey = tailwindPackage + ':' + config;
|
|
90
108
|
this.postcssProcessor = postcssProcessor.get(postCssInstanceKey)?.deref();
|
|
@@ -132,14 +150,12 @@ async function processStylesheet(language, data, filename, format, options, buil
|
|
|
132
150
|
watchFiles: [filename],
|
|
133
151
|
};
|
|
134
152
|
}
|
|
135
|
-
// Return early if there are no contents to further process
|
|
136
|
-
if (!result.contents) {
|
|
153
|
+
// Return early if there are no contents to further process or there are errors
|
|
154
|
+
if (!result.contents || result.errors?.length) {
|
|
137
155
|
return result;
|
|
138
156
|
}
|
|
139
|
-
// Only use postcss if Tailwind processing is required.
|
|
140
|
-
|
|
141
|
-
// be updated to account for the additional use.
|
|
142
|
-
if (postcssProcessor && !result.errors?.length && hasTailwindKeywords(result.contents)) {
|
|
157
|
+
// Only use postcss if Tailwind processing is required or custom postcss is present.
|
|
158
|
+
if (postcssProcessor && (options.postcssConfiguration || hasTailwindKeywords(result.contents))) {
|
|
143
159
|
const postcssResult = await compileString(typeof result.contents === 'string'
|
|
144
160
|
? result.contents
|
|
145
161
|
: Buffer.from(result.contents).toString('utf-8'), filename, postcssProcessor, options);
|
|
@@ -6,19 +6,15 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import { logging } from '@angular-devkit/core';
|
|
9
|
-
import { BuildOptions, Metafile, OutputFile
|
|
10
|
-
import { NormalizedOutputOptions } from '../../builders/application/options';
|
|
9
|
+
import { BuildOptions, Metafile, OutputFile } from 'esbuild';
|
|
10
|
+
import { NormalizedApplicationBuildOptions, NormalizedOutputOptions } from '../../builders/application/options';
|
|
11
11
|
import { BudgetCalculatorResult } from '../../utils/bundle-calculator';
|
|
12
12
|
import { BuildOutputFile, BuildOutputFileType, InitialFileRecord } from './bundler-context';
|
|
13
|
-
import { BuildOutputAsset } from './bundler-execution-result';
|
|
14
|
-
export declare function logBuildStats(
|
|
13
|
+
import { BuildOutputAsset, ExecutionResult } from './bundler-execution-result';
|
|
14
|
+
export declare function logBuildStats(metafile: Metafile, initial: Map<string, InitialFileRecord>, budgetFailures: BudgetCalculatorResult[] | undefined, colors: boolean, changedFiles?: Set<string>, estimatedTransferSizes?: Map<string, number>, ssrOutputEnabled?: boolean, verbose?: boolean): string;
|
|
15
15
|
export declare function calculateEstimatedTransferSizes(outputFiles: OutputFile[]): Promise<Map<string, number>>;
|
|
16
16
|
export declare function withSpinner<T>(text: string, action: () => T | Promise<T>): Promise<T>;
|
|
17
17
|
export declare function withNoProgress<T>(text: string, action: () => T | Promise<T>): Promise<T>;
|
|
18
|
-
export declare function logMessages(logger: logging.LoggerApi, { errors, warnings }: {
|
|
19
|
-
errors?: PartialMessage[];
|
|
20
|
-
warnings?: PartialMessage[];
|
|
21
|
-
}): Promise<void>;
|
|
22
18
|
/**
|
|
23
19
|
* Generates a syntax feature object map for Angular applications based on a list of targets.
|
|
24
20
|
* A full set of feature names can be found here: https://esbuild.github.io/api/#supported
|
|
@@ -41,3 +37,4 @@ export declare function transformSupportedBrowsersToTargets(supportedBrowsers: s
|
|
|
41
37
|
* @see https://esbuild.github.io/api/#target
|
|
42
38
|
*/
|
|
43
39
|
export declare function getSupportedNodeTargets(): string[];
|
|
40
|
+
export declare function logMessages(logger: logging.LoggerApi, executionResult: ExecutionResult, options: NormalizedApplicationBuildOptions): Promise<void>;
|