@angular-devkit/build-angular 17.1.0-next.1 → 17.1.0-next.3
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 +18 -18
- package/src/builders/application/build-action.d.ts +4 -3
- package/src/builders/application/build-action.js +24 -14
- package/src/builders/application/execute-build.js +3 -3
- package/src/builders/application/index.d.ts +20 -10
- package/src/builders/application/index.js +38 -26
- package/src/builders/application/options.d.ts +11 -3
- package/src/builders/application/options.js +39 -26
- package/src/builders/application/schema.d.ts +32 -2
- package/src/builders/application/schema.json +40 -2
- package/src/builders/browser-esbuild/builder-status-warnings.js +1 -3
- package/src/builders/browser-esbuild/index.js +8 -4
- package/src/builders/dev-server/builder.js +5 -0
- package/src/builders/dev-server/vite-server.js +16 -16
- package/src/builders/karma/index.js +4 -1
- package/src/builders/karma/schema.d.ts +6 -2
- package/src/builders/karma/schema.json +12 -2
- package/src/builders/ssr-dev-server/index.js +17 -31
- package/src/tools/esbuild/angular/angular-host.js +7 -1
- package/src/tools/esbuild/angular/compiler-plugin.js +11 -27
- package/src/tools/esbuild/angular/component-stylesheets.d.ts +3 -6
- package/src/tools/esbuild/angular/component-stylesheets.js +42 -47
- package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +2 -1
- package/src/tools/esbuild/angular/jit-plugin-callbacks.js +16 -16
- package/src/tools/esbuild/angular/source-file-cache.js +0 -1
- package/src/tools/esbuild/bundler-context.d.ts +1 -1
- package/src/tools/esbuild/bundler-context.js +18 -2
- package/src/tools/esbuild/compiler-plugin-options.js +5 -3
- package/src/tools/esbuild/global-styles.js +4 -2
- package/src/tools/esbuild/index-html-generator.js +3 -1
- package/src/tools/esbuild/stylesheets/bundle-options.d.ts +4 -1
- package/src/tools/esbuild/stylesheets/bundle-options.js +11 -6
- package/src/tools/esbuild/stylesheets/css-inline-fonts-plugin.d.ts +25 -0
- package/src/tools/esbuild/stylesheets/css-inline-fonts-plugin.js +57 -0
- package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +9 -1
- package/src/tools/esbuild/utils.d.ts +2 -2
- package/src/tools/esbuild/utils.js +61 -74
- package/src/tools/esbuild/watcher.js +56 -121
- package/src/utils/check-port.js +15 -29
- package/src/utils/delete-output-dir.d.ts +1 -1
- package/src/utils/delete-output-dir.js +11 -2
- package/src/utils/index-file/index-html-generator.js +15 -28
- package/src/utils/index-file/inline-fonts.d.ts +6 -1
- package/src/utils/index-file/inline-fonts.js +30 -14
- package/src/utils/index.d.ts +1 -0
- package/src/utils/index.js +1 -0
- package/src/{builders/dev-server → utils}/load-proxy-config.js +2 -2
- package/src/utils/server-rendering/esm-in-memory-loader/node-18-utils.js +6 -5
- package/src/tools/esbuild/normalize-path.d.ts +0 -8
- package/src/tools/esbuild/normalize-path.js +0 -22
- /package/src/{builders/dev-server → utils}/load-proxy-config.d.ts +0 -0
|
@@ -30,9 +30,7 @@ function logBuilderStatusWarnings(options, { logger }) {
|
|
|
30
30
|
if (typeof value === 'object' && Object.keys(value).length === 0) {
|
|
31
31
|
continue;
|
|
32
32
|
}
|
|
33
|
-
if (unsupportedOption === 'vendorChunk' ||
|
|
34
|
-
unsupportedOption === 'resourcesOutputPath' ||
|
|
35
|
-
unsupportedOption === 'deployUrl') {
|
|
33
|
+
if (unsupportedOption === 'vendorChunk' || unsupportedOption === 'resourcesOutputPath') {
|
|
36
34
|
logger.warn(`The '${unsupportedOption}' option is not used by this builder and will be ignored.`);
|
|
37
35
|
continue;
|
|
38
36
|
}
|
|
@@ -31,13 +31,13 @@ async function* buildEsbuildBrowser(userOptions, context, infrastructureSettings
|
|
|
31
31
|
(0, builder_status_warnings_1.logBuilderStatusWarnings)(userOptions, context);
|
|
32
32
|
const normalizedOptions = normalizeOptions(userOptions);
|
|
33
33
|
const { deleteOutputPath, outputPath } = normalizedOptions;
|
|
34
|
-
const fullOutputPath = node_path_1.default.join(context.workspaceRoot, outputPath);
|
|
34
|
+
const fullOutputPath = node_path_1.default.join(context.workspaceRoot, outputPath.base);
|
|
35
35
|
if (deleteOutputPath && infrastructureSettings?.write !== false) {
|
|
36
|
-
await (0, utils_2.deleteOutputDir)(context.workspaceRoot, outputPath);
|
|
36
|
+
await (0, utils_2.deleteOutputDir)(context.workspaceRoot, outputPath.base);
|
|
37
37
|
}
|
|
38
38
|
for await (const result of (0, application_1.buildApplicationInternal)(normalizedOptions, context, {
|
|
39
39
|
write: false,
|
|
40
|
-
}, plugins)) {
|
|
40
|
+
}, plugins && { codePlugins: plugins })) {
|
|
41
41
|
if (infrastructureSettings?.write !== false && result.outputFiles) {
|
|
42
42
|
// Write output files
|
|
43
43
|
await writeResultFiles(result.outputFiles, result.assetFiles, fullOutputPath);
|
|
@@ -55,11 +55,15 @@ async function* buildEsbuildBrowser(userOptions, context, infrastructureSettings
|
|
|
55
55
|
}
|
|
56
56
|
exports.buildEsbuildBrowser = buildEsbuildBrowser;
|
|
57
57
|
function normalizeOptions(options) {
|
|
58
|
-
const { main: browser, ngswConfigPath, serviceWorker, polyfills, ...otherOptions } = options;
|
|
58
|
+
const { main: browser, outputPath, ngswConfigPath, serviceWorker, polyfills, ...otherOptions } = options;
|
|
59
59
|
return {
|
|
60
60
|
browser,
|
|
61
61
|
serviceWorker: serviceWorker ? ngswConfigPath : false,
|
|
62
62
|
polyfills: typeof polyfills === 'string' ? [polyfills] : polyfills,
|
|
63
|
+
outputPath: {
|
|
64
|
+
base: outputPath,
|
|
65
|
+
browser: '',
|
|
66
|
+
},
|
|
63
67
|
...otherOptions,
|
|
64
68
|
};
|
|
65
69
|
}
|
|
@@ -65,6 +65,11 @@ function execute(options, context, transforms = {}, extensions) {
|
|
|
65
65
|
if (transforms?.logging || transforms?.webpackConfiguration) {
|
|
66
66
|
throw new Error('The `application` and `browser-esbuild` builders do not support Webpack transforms.');
|
|
67
67
|
}
|
|
68
|
+
if (normalizedOptions.forceEsbuild &&
|
|
69
|
+
builderName === '@angular-devkit/build-angular:browser') {
|
|
70
|
+
// The compatibility builder should be used if esbuild is force enabled with the official Webpack-based builder.
|
|
71
|
+
builderName = '@angular-devkit/build-angular:browser-esbuild';
|
|
72
|
+
}
|
|
68
73
|
return (0, rxjs_1.defer)(() => Promise.resolve().then(() => __importStar(require('./vite-server')))).pipe((0, rxjs_1.switchMap)(({ serveWithVite }) => serveWithVite(normalizedOptions, builderName, context, transforms, extensions)));
|
|
69
74
|
}
|
|
70
75
|
if (extensions?.buildPlugins?.length) {
|
|
@@ -51,7 +51,6 @@ const supported_browsers_1 = require("../../utils/supported-browsers");
|
|
|
51
51
|
const webpack_browser_config_1 = require("../../utils/webpack-browser-config");
|
|
52
52
|
const application_1 = require("../application");
|
|
53
53
|
const browser_esbuild_1 = require("../browser-esbuild");
|
|
54
|
-
const load_proxy_config_1 = require("./load-proxy-config");
|
|
55
54
|
// eslint-disable-next-line max-lines-per-function
|
|
56
55
|
async function* serveWithVite(serverOptions, builderName, context, transformers, extensions) {
|
|
57
56
|
// Get the browser configuration from the target name.
|
|
@@ -74,8 +73,11 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
74
73
|
}
|
|
75
74
|
// Set all packages as external to support Vite's prebundle caching
|
|
76
75
|
browserOptions.externalPackages = serverOptions.cacheOptions.enabled;
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
const baseHref = browserOptions.baseHref;
|
|
77
|
+
if (serverOptions.servePath === undefined && baseHref !== undefined) {
|
|
78
|
+
// Remove trailing slash
|
|
79
|
+
serverOptions.servePath =
|
|
80
|
+
baseHref[baseHref.length - 1] === '/' ? baseHref.slice(0, -1) : baseHref;
|
|
79
81
|
}
|
|
80
82
|
// The development server currently only supports a single locale when localizing.
|
|
81
83
|
// This matches the behavior of the Webpack-based development server but could be expanded in the future.
|
|
@@ -119,14 +121,10 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
119
121
|
deferred?.();
|
|
120
122
|
});
|
|
121
123
|
const build = builderName === '@angular-devkit/build-angular:browser-esbuild'
|
|
122
|
-
? browser_esbuild_1.buildEsbuildBrowser
|
|
123
|
-
: application_1.buildApplicationInternal;
|
|
124
|
+
? browser_esbuild_1.buildEsbuildBrowser.bind(undefined, browserOptions, context, { write: false }, extensions?.buildPlugins)
|
|
125
|
+
: application_1.buildApplicationInternal.bind(undefined, browserOptions, context, { write: false }, { codePlugins: extensions?.buildPlugins });
|
|
124
126
|
// TODO: Switch this to an architect schedule call when infrastructure settings are supported
|
|
125
|
-
for await (const result of build(
|
|
126
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
127
|
-
browserOptions, context, {
|
|
128
|
-
write: false,
|
|
129
|
-
}, extensions?.buildPlugins)) {
|
|
127
|
+
for await (const result of build()) {
|
|
130
128
|
(0, node_assert_1.default)(result.outputFiles, 'Builder did not provide result files.');
|
|
131
129
|
// If build failed, nothing to serve
|
|
132
130
|
if (!result.success) {
|
|
@@ -179,7 +177,7 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
|
|
|
179
177
|
if (server) {
|
|
180
178
|
// Update fs allow list to include any new assets from the build option.
|
|
181
179
|
server.config.server.fs.allow = [
|
|
182
|
-
...new Set(...server.config.server.fs.allow, ...assetFiles.values()),
|
|
180
|
+
...new Set([...server.config.server.fs.allow, ...assetFiles.values()]),
|
|
183
181
|
];
|
|
184
182
|
handleUpdate(normalizePath, generatedFiles, server, serverOptions, context.logger);
|
|
185
183
|
}
|
|
@@ -328,7 +326,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
|
|
|
328
326
|
}
|
|
329
327
|
// eslint-disable-next-line max-lines-per-function
|
|
330
328
|
async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
|
|
331
|
-
const proxy = await (0,
|
|
329
|
+
const proxy = await (0, utils_2.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig, true);
|
|
332
330
|
// dynamically import Vite for ESM compatibility
|
|
333
331
|
const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
|
|
334
332
|
// Path will not exist on disk and only used to provide separate path for Vite requests
|
|
@@ -350,7 +348,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
350
348
|
css: {
|
|
351
349
|
devSourcemap: true,
|
|
352
350
|
},
|
|
353
|
-
// Vite will normalize the `base` option by adding a leading
|
|
351
|
+
// Vite will normalize the `base` option by adding a leading slash.
|
|
354
352
|
base: serverOptions.servePath,
|
|
355
353
|
resolve: {
|
|
356
354
|
mainFields: ['es2020', 'browser', 'module', 'main'],
|
|
@@ -476,6 +474,10 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
476
474
|
// Rewrite all build assets to a vite raw fs URL
|
|
477
475
|
const assetSourcePath = assets.get(pathname);
|
|
478
476
|
if (assetSourcePath !== undefined) {
|
|
477
|
+
// Workaround to disable Vite transformer middleware.
|
|
478
|
+
// See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
|
|
479
|
+
// https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
|
|
480
|
+
req.headers.accept = 'text/html';
|
|
479
481
|
// The encoding needs to match what happens in the vite static middleware.
|
|
480
482
|
// ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
|
|
481
483
|
req.url = `${server.config.base}@fs/${encodeURI(assetSourcePath)}`;
|
|
@@ -525,11 +527,9 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
|
|
|
525
527
|
return;
|
|
526
528
|
}
|
|
527
529
|
transformIndexHtmlAndAddHeaders(url, rawHtml, res, next, async (html) => {
|
|
528
|
-
const protocol = serverOptions.ssl ? 'https' : 'http';
|
|
529
|
-
const route = `${protocol}://${req.headers.host}${req.originalUrl}`;
|
|
530
530
|
const { content } = await (0, render_page_1.renderPage)({
|
|
531
531
|
document: html,
|
|
532
|
-
route,
|
|
532
|
+
route: new URL(req.originalUrl ?? '/', server.resolvedUrls?.local[0]).toString(),
|
|
533
533
|
serverContext: 'ssr',
|
|
534
534
|
loadBundle: (uri) =>
|
|
535
535
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -90,9 +90,12 @@ function execute(options, context, transforms = {}) {
|
|
|
90
90
|
: getBuiltInKarmaConfig(context.workspaceRoot, projectName);
|
|
91
91
|
karmaOptions.singleRun = singleRun;
|
|
92
92
|
// Convert browsers from a string to an array
|
|
93
|
-
if (options.browsers) {
|
|
93
|
+
if (typeof options.browsers === 'string' && options.browsers) {
|
|
94
94
|
karmaOptions.browsers = options.browsers.split(',');
|
|
95
95
|
}
|
|
96
|
+
else if (options.browsers === false) {
|
|
97
|
+
karmaOptions.browsers = [];
|
|
98
|
+
}
|
|
96
99
|
if (options.reporters) {
|
|
97
100
|
// Split along commas to make it more natural, and remove empty strings.
|
|
98
101
|
const reporters = options.reporters
|
|
@@ -7,9 +7,9 @@ export interface Schema {
|
|
|
7
7
|
*/
|
|
8
8
|
assets?: AssetPattern[];
|
|
9
9
|
/**
|
|
10
|
-
* Override which browsers tests are run against.
|
|
10
|
+
* Override which browsers tests are run against. Set to `false` to not use any browser.
|
|
11
11
|
*/
|
|
12
|
-
browsers?:
|
|
12
|
+
browsers?: Browsers;
|
|
13
13
|
/**
|
|
14
14
|
* Output a code coverage report.
|
|
15
15
|
*/
|
|
@@ -117,6 +117,10 @@ export interface AssetPatternClass {
|
|
|
117
117
|
*/
|
|
118
118
|
output: string;
|
|
119
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Override which browsers tests are run against. Set to `false` to not use any browser.
|
|
122
|
+
*/
|
|
123
|
+
export type Browsers = boolean | string;
|
|
120
124
|
export interface FileReplacement {
|
|
121
125
|
replace?: string;
|
|
122
126
|
replaceWith?: string;
|
|
@@ -199,8 +199,18 @@
|
|
|
199
199
|
"description": "Do not use the real path when resolving modules. If unset then will default to `true` if NodeJS option --preserve-symlinks is set."
|
|
200
200
|
},
|
|
201
201
|
"browsers": {
|
|
202
|
-
"
|
|
203
|
-
"
|
|
202
|
+
"description": "Override which browsers tests are run against. Set to `false` to not use any browser.",
|
|
203
|
+
"oneOf": [
|
|
204
|
+
{
|
|
205
|
+
"type": "string",
|
|
206
|
+
"description": "A comma seperate list of browsers to run tests against."
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"const": false,
|
|
210
|
+
"type": "boolean",
|
|
211
|
+
"description": "Does use run tests against a browser."
|
|
212
|
+
}
|
|
213
|
+
]
|
|
204
214
|
},
|
|
205
215
|
"codeCoverage": {
|
|
206
216
|
"type": "boolean",
|
|
@@ -36,8 +36,8 @@ const core_1 = require("@angular-devkit/core");
|
|
|
36
36
|
const path_1 = require("path");
|
|
37
37
|
const rxjs_1 = require("rxjs");
|
|
38
38
|
const url = __importStar(require("url"));
|
|
39
|
-
const
|
|
40
|
-
const
|
|
39
|
+
const utils_1 = require("../../utils");
|
|
40
|
+
const utils_2 = require("./utils");
|
|
41
41
|
/** Log messages to ignore and not rely to the logger */
|
|
42
42
|
const IGNORED_STDOUT_MESSAGES = [
|
|
43
43
|
'server listening on',
|
|
@@ -78,7 +78,7 @@ function execute(options, context) {
|
|
|
78
78
|
DON'T USE IT FOR PRODUCTION!
|
|
79
79
|
****************************************************************************************
|
|
80
80
|
`);
|
|
81
|
-
return (0, rxjs_1.zip)(browserTargetRun, serverTargetRun, (0,
|
|
81
|
+
return (0, rxjs_1.zip)(browserTargetRun, serverTargetRun, (0, utils_2.getAvailablePort)()).pipe((0, rxjs_1.switchMap)(([br, sr, nodeServerPort]) => {
|
|
82
82
|
return (0, rxjs_1.combineLatest)([br.output, sr.output]).pipe(
|
|
83
83
|
// This is needed so that if both server and browser emit close to each other
|
|
84
84
|
// we only emit once. This typically happens on the first build.
|
|
@@ -101,7 +101,7 @@ function execute(options, context) {
|
|
|
101
101
|
context.logger.info('\nCompiled successfully.');
|
|
102
102
|
}
|
|
103
103
|
}), (0, rxjs_1.debounce)(([builderOutput]) => builderOutput.success && !options.inspect
|
|
104
|
-
? (0,
|
|
104
|
+
? (0, utils_2.waitUntilServerIsListening)(nodeServerPort)
|
|
105
105
|
: rxjs_1.EMPTY), (0, rxjs_1.finalize)(() => {
|
|
106
106
|
void br.stop();
|
|
107
107
|
void sr.stop();
|
|
@@ -162,7 +162,7 @@ function startNodeServer(serverOutput, port, logger, inspectMode = false) {
|
|
|
162
162
|
args.unshift('--inspect-brk');
|
|
163
163
|
}
|
|
164
164
|
return (0, rxjs_1.of)(null).pipe((0, rxjs_1.delay)(0), // Avoid EADDRINUSE error since it will cause the kill event to be finish.
|
|
165
|
-
(0, rxjs_1.switchMap)(() => (0,
|
|
165
|
+
(0, rxjs_1.switchMap)(() => (0, utils_2.spawnAsObservable)('node', args, { env, shell: true })), (0, rxjs_1.tap)((res) => log({ stderr: res.stderr, stdout: res.stdout }, logger)), (0, rxjs_1.ignoreElements)(),
|
|
166
166
|
// Emit a signal after the process has been started
|
|
167
167
|
(0, rxjs_1.startWith)(undefined));
|
|
168
168
|
}
|
|
@@ -171,7 +171,7 @@ async function initBrowserSync(browserSyncInstance, nodeServerPort, options, con
|
|
|
171
171
|
return browserSyncInstance;
|
|
172
172
|
}
|
|
173
173
|
const { port: browserSyncPort, open, host, publicHost, proxyConfig } = options;
|
|
174
|
-
const bsPort = browserSyncPort || (await (0,
|
|
174
|
+
const bsPort = browserSyncPort || (await (0, utils_2.getAvailablePort)());
|
|
175
175
|
const bsOptions = {
|
|
176
176
|
proxy: {
|
|
177
177
|
target: `localhost:${nodeServerPort}`,
|
|
@@ -283,33 +283,19 @@ function getSslConfig(root, options) {
|
|
|
283
283
|
return ssl;
|
|
284
284
|
}
|
|
285
285
|
async function getProxyConfig(root, proxyConfig) {
|
|
286
|
-
const
|
|
287
|
-
let proxySettings;
|
|
288
|
-
try {
|
|
289
|
-
proxySettings = require(proxyPath);
|
|
290
|
-
}
|
|
291
|
-
catch (error) {
|
|
292
|
-
(0, error_1.assertIsError)(error);
|
|
293
|
-
if (error.code === 'MODULE_NOT_FOUND') {
|
|
294
|
-
throw new Error(`Proxy config file ${proxyPath} does not exist.`);
|
|
295
|
-
}
|
|
296
|
-
throw error;
|
|
297
|
-
}
|
|
298
|
-
const proxies = Array.isArray(proxySettings) ? proxySettings : [proxySettings];
|
|
286
|
+
const proxy = await (0, utils_1.loadProxyConfiguration)(root, proxyConfig, false);
|
|
299
287
|
const createdProxies = [];
|
|
300
288
|
const { createProxyMiddleware } = await Promise.resolve().then(() => __importStar(require('http-proxy-middleware')));
|
|
301
|
-
for (const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
createProxyMiddleware(key, context));
|
|
312
|
-
}
|
|
289
|
+
for (const [key, context] of Object.entries(proxy)) {
|
|
290
|
+
if (typeof key === 'string') {
|
|
291
|
+
createdProxies.push(createProxyMiddleware(key.replace(/^\*$/, '**').replace(/\/\*$/, ''),
|
|
292
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
293
|
+
context));
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
createdProxies.push(
|
|
297
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
298
|
+
createProxyMiddleware(key, context));
|
|
313
299
|
}
|
|
314
300
|
}
|
|
315
301
|
return createdProxies;
|
|
@@ -28,6 +28,12 @@ exports.ensureSourceFileVersions = ensureSourceFileVersions;
|
|
|
28
28
|
function createAngularCompilerHost(compilerOptions, hostOptions) {
|
|
29
29
|
// Create TypeScript compiler host
|
|
30
30
|
const host = typescript_1.default.createIncrementalCompilerHost(compilerOptions);
|
|
31
|
+
// Set the parsing mode to the same as TS 5.3 default for tsc. This provides a parse
|
|
32
|
+
// performance improvement by skipping non-type related JSDoc parsing.
|
|
33
|
+
// NOTE: The check for this enum can be removed when TS 5.3 support is the minimum.
|
|
34
|
+
if (typescript_1.default.JSDocParsingMode) {
|
|
35
|
+
host.jsDocParsingMode = typescript_1.default.JSDocParsingMode.ParseForTypeErrors;
|
|
36
|
+
}
|
|
31
37
|
// The AOT compiler currently requires this hook to allow for a transformResource hook.
|
|
32
38
|
// Once the AOT compiler allows only a transformResource hook, this can be reevaluated.
|
|
33
39
|
host.readResource = async function (filename) {
|
|
@@ -40,7 +46,7 @@ function createAngularCompilerHost(compilerOptions, hostOptions) {
|
|
|
40
46
|
return null;
|
|
41
47
|
}
|
|
42
48
|
const result = await hostOptions.transformStylesheet(data, context.containingFile, context.resourceFile ?? undefined);
|
|
43
|
-
return result ? { content: result } : null;
|
|
49
|
+
return typeof result === 'string' ? { content: result } : null;
|
|
44
50
|
};
|
|
45
51
|
// Allow the AOT compiler to request the set of changed templates and styles
|
|
46
52
|
host.getModifiedResourceFiles = function () {
|
|
@@ -35,7 +35,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.createCompilerPlugin = void 0;
|
|
37
37
|
const node_assert_1 = __importDefault(require("node:assert"));
|
|
38
|
-
const node_fs_1 = require("node:fs");
|
|
39
38
|
const path = __importStar(require("node:path"));
|
|
40
39
|
const environment_options_1 = require("../../../utils/environment-options");
|
|
41
40
|
const javascript_transformer_1 = require("../javascript-transformer");
|
|
@@ -54,18 +53,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
54
53
|
async setup(build) {
|
|
55
54
|
let setupWarnings = [];
|
|
56
55
|
const preserveSymlinks = build.initialOptions.preserveSymlinks;
|
|
57
|
-
let tsconfigPath = pluginOptions.tsconfig;
|
|
58
|
-
if (!preserveSymlinks) {
|
|
59
|
-
// Use the real path of the tsconfig if not preserving symlinks.
|
|
60
|
-
// This ensures the TS source file paths are based on the real path of the configuration.
|
|
61
|
-
// NOTE: promises.realpath should not be used here since it uses realpath.native which
|
|
62
|
-
// can cause case conversion and other undesirable behavior on Windows systems.
|
|
63
|
-
// ref: https://github.com/nodejs/node/issues/7726
|
|
64
|
-
try {
|
|
65
|
-
tsconfigPath = (0, node_fs_1.realpathSync)(tsconfigPath);
|
|
66
|
-
}
|
|
67
|
-
catch { }
|
|
68
|
-
}
|
|
69
56
|
// Initialize a worker pool for JavaScript transformations
|
|
70
57
|
const javascriptTransformer = new javascript_transformer_1.JavaScriptTransformer(pluginOptions, environment_options_1.maxWorkers);
|
|
71
58
|
// Setup defines based on the values used by the Angular compiler-cli
|
|
@@ -132,14 +119,14 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
132
119
|
else {
|
|
133
120
|
stylesheetResult = await stylesheetBundler.bundleInline(data, containingFile, styleOptions.inlineStyleLanguage);
|
|
134
121
|
}
|
|
135
|
-
const { contents,
|
|
122
|
+
const { contents, outputFiles, metafile, referencedFiles, errors, warnings } = stylesheetResult;
|
|
136
123
|
if (errors) {
|
|
137
124
|
(result.errors ??= []).push(...errors);
|
|
138
125
|
}
|
|
139
126
|
(result.warnings ??= []).push(...warnings);
|
|
140
127
|
additionalResults.set(stylesheetFile ?? containingFile, {
|
|
141
|
-
outputFiles
|
|
142
|
-
metafile
|
|
128
|
+
outputFiles,
|
|
129
|
+
metafile,
|
|
143
130
|
});
|
|
144
131
|
if (referencedFiles) {
|
|
145
132
|
referencedFileTracker.add(containingFile, referencedFiles);
|
|
@@ -185,7 +172,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
185
172
|
// In watch mode, previous build state will be reused.
|
|
186
173
|
let referencedFiles;
|
|
187
174
|
try {
|
|
188
|
-
const initializationResult = await compilation.initialize(
|
|
175
|
+
const initializationResult = await compilation.initialize(pluginOptions.tsconfig, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks));
|
|
189
176
|
shouldTsIgnoreJs = !initializationResult.compilerOptions.allowJs;
|
|
190
177
|
referencedFiles = initializationResult.referencedFiles;
|
|
191
178
|
}
|
|
@@ -308,7 +295,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
|
|
|
308
295
|
}));
|
|
309
296
|
// Setup bundling of component templates and stylesheets when in JIT mode
|
|
310
297
|
if (pluginOptions.jit) {
|
|
311
|
-
(0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage);
|
|
298
|
+
(0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage, pluginOptions.loadResultCache);
|
|
312
299
|
}
|
|
313
300
|
build.onEnd((result) => {
|
|
314
301
|
// Ensure other compilations are unblocked if the main compilation throws during start
|
|
@@ -401,22 +388,19 @@ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserve
|
|
|
401
388
|
function bundleWebWorker(build, pluginOptions, workerFile) {
|
|
402
389
|
try {
|
|
403
390
|
return build.esbuild.buildSync({
|
|
391
|
+
...build.initialOptions,
|
|
404
392
|
platform: 'browser',
|
|
405
393
|
write: false,
|
|
406
394
|
bundle: true,
|
|
407
395
|
metafile: true,
|
|
408
396
|
format: 'esm',
|
|
409
|
-
mainFields: ['es2020', 'es2015', 'browser', 'module', 'main'],
|
|
410
|
-
logLevel: 'silent',
|
|
411
|
-
sourcemap: pluginOptions.sourcemap,
|
|
412
397
|
entryNames: 'worker-[hash]',
|
|
413
398
|
entryPoints: [workerFile],
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
target: build.initialOptions.target,
|
|
399
|
+
sourcemap: pluginOptions.sourcemap,
|
|
400
|
+
// Zone.js is not used in Web workers so no need to disable
|
|
401
|
+
supported: undefined,
|
|
402
|
+
// Plugins are not supported in sync esbuild calls
|
|
403
|
+
plugins: undefined,
|
|
420
404
|
});
|
|
421
405
|
}
|
|
422
406
|
catch (error) {
|
|
@@ -26,9 +26,7 @@ export declare class ComponentStylesheetBundler {
|
|
|
26
26
|
errors: import("esbuild").Message[] | undefined;
|
|
27
27
|
warnings: import("esbuild").Message[];
|
|
28
28
|
contents: string;
|
|
29
|
-
|
|
30
|
-
path: string | undefined;
|
|
31
|
-
resourceFiles: OutputFile[];
|
|
29
|
+
outputFiles: OutputFile[];
|
|
32
30
|
metafile: import("esbuild").Metafile | undefined;
|
|
33
31
|
referencedFiles: Set<string> | undefined;
|
|
34
32
|
}>;
|
|
@@ -36,12 +34,11 @@ export declare class ComponentStylesheetBundler {
|
|
|
36
34
|
errors: import("esbuild").Message[] | undefined;
|
|
37
35
|
warnings: import("esbuild").Message[];
|
|
38
36
|
contents: string;
|
|
39
|
-
|
|
40
|
-
path: string | undefined;
|
|
41
|
-
resourceFiles: OutputFile[];
|
|
37
|
+
outputFiles: OutputFile[];
|
|
42
38
|
metafile: import("esbuild").Metafile | undefined;
|
|
43
39
|
referencedFiles: Set<string> | undefined;
|
|
44
40
|
}>;
|
|
45
41
|
invalidate(files: Iterable<string>): void;
|
|
46
42
|
dispose(): Promise<void>;
|
|
43
|
+
private extractResult;
|
|
47
44
|
}
|
|
@@ -52,7 +52,7 @@ class ComponentStylesheetBundler {
|
|
|
52
52
|
return buildOptions;
|
|
53
53
|
});
|
|
54
54
|
});
|
|
55
|
-
return extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
|
|
55
|
+
return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
|
|
56
56
|
}
|
|
57
57
|
async bundleInline(data, filename, language) {
|
|
58
58
|
// Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve
|
|
@@ -79,7 +79,7 @@ class ComponentStylesheetBundler {
|
|
|
79
79
|
namespace,
|
|
80
80
|
};
|
|
81
81
|
});
|
|
82
|
-
build.onLoad({ filter: /^css;/, namespace },
|
|
82
|
+
build.onLoad({ filter: /^css;/, namespace }, () => {
|
|
83
83
|
return {
|
|
84
84
|
contents: data,
|
|
85
85
|
loader: 'css',
|
|
@@ -92,7 +92,7 @@ class ComponentStylesheetBundler {
|
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
// Extract the result of the bundling from the output files
|
|
95
|
-
return extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
|
|
95
|
+
return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
|
|
96
96
|
}
|
|
97
97
|
invalidate(files) {
|
|
98
98
|
if (!this.incremental) {
|
|
@@ -112,51 +112,46 @@ class ComponentStylesheetBundler {
|
|
|
112
112
|
this.#inlineContexts.clear();
|
|
113
113
|
await Promise.allSettled(contexts.map((context) => context.dispose()));
|
|
114
114
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
throw new Error(`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`);
|
|
115
|
+
extractResult(result, referencedFiles) {
|
|
116
|
+
let contents = '';
|
|
117
|
+
let metafile;
|
|
118
|
+
const outputFiles = [];
|
|
119
|
+
if (!result.errors) {
|
|
120
|
+
for (const outputFile of result.outputFiles) {
|
|
121
|
+
const filename = node_path_1.default.basename(outputFile.path);
|
|
122
|
+
// Needed for Bazel as otherwise the files will not be written in the correct place.
|
|
123
|
+
outputFile.path = node_path_1.default.join(this.options.workspaceRoot, outputFile.path);
|
|
124
|
+
if (outputFile.type === bundler_context_1.BuildOutputFileType.Media) {
|
|
125
|
+
// The output files could also contain resources (images/fonts/etc.) that were referenced
|
|
126
|
+
outputFiles.push(outputFile);
|
|
127
|
+
}
|
|
128
|
+
else if (filename.endsWith('.css')) {
|
|
129
|
+
contents = outputFile.text;
|
|
130
|
+
}
|
|
131
|
+
else if (filename.endsWith('.css.map')) {
|
|
132
|
+
outputFiles.push(outputFile);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
throw new Error(`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`);
|
|
136
|
+
}
|
|
138
137
|
}
|
|
138
|
+
metafile = result.metafile;
|
|
139
|
+
// Remove entryPoint fields from outputs to prevent the internal component styles from being
|
|
140
|
+
// treated as initial files. Also mark the entry as a component resource for stat reporting.
|
|
141
|
+
Object.values(metafile.outputs).forEach((output) => {
|
|
142
|
+
delete output.entryPoint;
|
|
143
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
144
|
+
output['ng-component'] = true;
|
|
145
|
+
});
|
|
139
146
|
}
|
|
147
|
+
return {
|
|
148
|
+
errors: result.errors,
|
|
149
|
+
warnings: result.warnings,
|
|
150
|
+
contents,
|
|
151
|
+
outputFiles,
|
|
152
|
+
metafile,
|
|
153
|
+
referencedFiles,
|
|
154
|
+
};
|
|
140
155
|
}
|
|
141
|
-
let metafile;
|
|
142
|
-
if (!result.errors) {
|
|
143
|
-
metafile = result.metafile;
|
|
144
|
-
// Remove entryPoint fields from outputs to prevent the internal component styles from being
|
|
145
|
-
// treated as initial files. Also mark the entry as a component resource for stat reporting.
|
|
146
|
-
Object.values(metafile.outputs).forEach((output) => {
|
|
147
|
-
delete output.entryPoint;
|
|
148
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
149
|
-
output['ng-component'] = true;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
errors: result.errors,
|
|
154
|
-
warnings: result.warnings,
|
|
155
|
-
contents,
|
|
156
|
-
map,
|
|
157
|
-
path: outputPath,
|
|
158
|
-
resourceFiles,
|
|
159
|
-
metafile,
|
|
160
|
-
referencedFiles,
|
|
161
|
-
};
|
|
162
156
|
}
|
|
157
|
+
exports.ComponentStylesheetBundler = ComponentStylesheetBundler;
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* found in the LICENSE file at https://angular.io/license
|
|
7
7
|
*/
|
|
8
8
|
import type { Metafile, OutputFile, PluginBuild } from 'esbuild';
|
|
9
|
+
import { LoadResultCache } from '../load-result-cache';
|
|
9
10
|
import { ComponentStylesheetBundler } from './component-stylesheets';
|
|
10
11
|
/**
|
|
11
12
|
* Sets up esbuild resolve and load callbacks to support Angular JIT mode processing
|
|
@@ -19,4 +20,4 @@ import { ComponentStylesheetBundler } from './component-stylesheets';
|
|
|
19
20
|
export declare function setupJitPluginCallbacks(build: PluginBuild, stylesheetBundler: ComponentStylesheetBundler, additionalResultFiles: Map<string, {
|
|
20
21
|
outputFiles?: OutputFile[];
|
|
21
22
|
metafile?: Metafile;
|
|
22
|
-
}>, inlineStyleLanguage: string): void;
|
|
23
|
+
}>, inlineStyleLanguage: string, loadCache?: LoadResultCache): void;
|