@angular-devkit/build-angular 17.1.0-next.2 → 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.
Files changed (31) hide show
  1. package/package.json +10 -10
  2. package/src/builders/application/build-action.d.ts +4 -3
  3. package/src/builders/application/build-action.js +8 -5
  4. package/src/builders/application/execute-build.js +3 -3
  5. package/src/builders/application/index.d.ts +20 -10
  6. package/src/builders/application/index.js +38 -26
  7. package/src/builders/application/options.d.ts +11 -3
  8. package/src/builders/application/options.js +39 -26
  9. package/src/builders/application/schema.d.ts +32 -2
  10. package/src/builders/application/schema.json +40 -2
  11. package/src/builders/browser-esbuild/index.js +8 -4
  12. package/src/builders/dev-server/vite-server.js +5 -12
  13. package/src/builders/ssr-dev-server/index.js +17 -31
  14. package/src/tools/esbuild/angular/angular-host.js +1 -1
  15. package/src/tools/esbuild/angular/compiler-plugin.js +10 -26
  16. package/src/tools/esbuild/angular/component-stylesheets.d.ts +3 -6
  17. package/src/tools/esbuild/angular/component-stylesheets.js +41 -46
  18. package/src/tools/esbuild/angular/jit-plugin-callbacks.js +2 -2
  19. package/src/tools/esbuild/bundler-context.d.ts +1 -1
  20. package/src/tools/esbuild/bundler-context.js +18 -2
  21. package/src/tools/esbuild/compiler-plugin-options.js +1 -1
  22. package/src/tools/esbuild/index-html-generator.js +3 -1
  23. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +1 -1
  24. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.js +9 -1
  25. package/src/tools/esbuild/utils.d.ts +2 -2
  26. package/src/tools/esbuild/utils.js +61 -74
  27. package/src/utils/index-file/index-html-generator.js +15 -28
  28. package/src/utils/index.d.ts +1 -0
  29. package/src/utils/index.js +1 -0
  30. package/src/{builders/dev-server → utils}/load-proxy-config.js +2 -2
  31. /package/src/{builders/dev-server → utils}/load-proxy-config.d.ts +0 -0
@@ -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.
@@ -122,14 +121,10 @@ async function* serveWithVite(serverOptions, builderName, context, transformers,
122
121
  deferred?.();
123
122
  });
124
123
  const build = builderName === '@angular-devkit/build-angular:browser-esbuild'
125
- ? browser_esbuild_1.buildEsbuildBrowser
126
- : 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 });
127
126
  // TODO: Switch this to an architect schedule call when infrastructure settings are supported
128
- for await (const result of build(
129
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
- browserOptions, context, {
131
- write: false,
132
- }, extensions?.buildPlugins)) {
127
+ for await (const result of build()) {
133
128
  (0, node_assert_1.default)(result.outputFiles, 'Builder did not provide result files.');
134
129
  // If build failed, nothing to serve
135
130
  if (!result.success) {
@@ -331,7 +326,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
331
326
  }
332
327
  // eslint-disable-next-line max-lines-per-function
333
328
  async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssr, prebundleTransformer, target, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
334
- const proxy = await (0, load_proxy_config_1.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig, true);
329
+ const proxy = await (0, utils_2.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig, true);
335
330
  // dynamically import Vite for ESM compatibility
336
331
  const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
337
332
  // Path will not exist on disk and only used to provide separate path for Vite requests
@@ -532,11 +527,9 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
532
527
  return;
533
528
  }
534
529
  transformIndexHtmlAndAddHeaders(url, rawHtml, res, next, async (html) => {
535
- const protocol = serverOptions.ssl ? 'https' : 'http';
536
- const route = `${protocol}://${req.headers.host}${req.originalUrl}`;
537
530
  const { content } = await (0, render_page_1.renderPage)({
538
531
  document: html,
539
- route,
532
+ route: new URL(req.originalUrl ?? '/', server.resolvedUrls?.local[0]).toString(),
540
533
  serverContext: 'ssr',
541
534
  loadBundle: (uri) =>
542
535
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -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 error_1 = require("../../utils/error");
40
- const utils_1 = require("./utils");
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, utils_1.getAvailablePort)()).pipe((0, rxjs_1.switchMap)(([br, sr, nodeServerPort]) => {
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, utils_1.waitUntilServerIsListening)(nodeServerPort)
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, utils_1.spawnAsObservable)('node', args, { env, shell: true })), (0, rxjs_1.tap)((res) => log({ stderr: res.stderr, stdout: res.stdout }, logger)), (0, rxjs_1.ignoreElements)(),
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, utils_1.getAvailablePort)());
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 proxyPath = (0, path_1.resolve)(root, proxyConfig);
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 proxy of proxies) {
302
- for (const [key, context] of Object.entries(proxy)) {
303
- if (typeof key === 'string') {
304
- createdProxies.push(createProxyMiddleware(key.replace(/^\*$/, '**').replace(/\/\*$/, ''),
305
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
306
- context));
307
- }
308
- else {
309
- createdProxies.push(
310
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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;
@@ -46,7 +46,7 @@ function createAngularCompilerHost(compilerOptions, hostOptions) {
46
46
  return null;
47
47
  }
48
48
  const result = await hostOptions.transformStylesheet(data, context.containingFile, context.resourceFile ?? undefined);
49
- return result ? { content: result } : null;
49
+ return typeof result === 'string' ? { content: result } : null;
50
50
  };
51
51
  // Allow the AOT compiler to request the set of changed templates and styles
52
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, resourceFiles, referencedFiles, errors, warnings } = stylesheetResult;
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: resourceFiles,
142
- metafile: stylesheetResult.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(tsconfigPath, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks));
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
  }
@@ -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
- absWorkingDir: build.initialOptions.absWorkingDir,
415
- outdir: build.initialOptions.outdir,
416
- minifyIdentifiers: build.initialOptions.minifyIdentifiers,
417
- minifySyntax: build.initialOptions.minifySyntax,
418
- minifyWhitespace: build.initialOptions.minifyWhitespace,
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
- map: string | undefined;
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
- map: string | undefined;
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
@@ -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
- exports.ComponentStylesheetBundler = ComponentStylesheetBundler;
117
- function extractResult(result, referencedFiles) {
118
- let contents = '';
119
- let map;
120
- let outputPath;
121
- const resourceFiles = [];
122
- if (!result.errors) {
123
- for (const outputFile of result.outputFiles) {
124
- const filename = node_path_1.default.basename(outputFile.path);
125
- if (outputFile.type === bundler_context_1.BuildOutputFileType.Media) {
126
- // The output files could also contain resources (images/fonts/etc.) that were referenced
127
- resourceFiles.push(outputFile);
128
- }
129
- else if (filename.endsWith('.css')) {
130
- outputPath = outputFile.path;
131
- contents = outputFile.text;
132
- }
133
- else if (filename.endsWith('.css.map')) {
134
- map = outputFile.text;
135
- }
136
- else {
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;
@@ -92,8 +92,8 @@ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles
92
92
  else {
93
93
  stylesheetResult = await stylesheetBundler.bundleInline(entry.contents, entry.path, inlineStyleLanguage);
94
94
  }
95
- const { contents, resourceFiles, errors, warnings, metafile, referencedFiles } = stylesheetResult;
96
- additionalResultFiles.set(entry.path, { outputFiles: resourceFiles, metafile });
95
+ const { contents, outputFiles, errors, warnings, metafile, referencedFiles } = stylesheetResult;
96
+ additionalResultFiles.set(entry.path, { outputFiles, metafile });
97
97
  return {
98
98
  errors,
99
99
  warnings,
@@ -20,6 +20,7 @@ export type BundleContextResult = {
20
20
  server?: Set<string>;
21
21
  browser?: Set<string>;
22
22
  };
23
+ externalConfiguration?: string[];
23
24
  };
24
25
  export interface InitialFileRecord {
25
26
  entrypoint: boolean;
@@ -35,7 +36,6 @@ export declare enum BuildOutputFileType {
35
36
  }
36
37
  export interface BuildOutputFile extends OutputFile {
37
38
  type: BuildOutputFileType;
38
- fullOutputPath: string;
39
39
  clone: () => BuildOutputFile;
40
40
  }
41
41
  export type BundlerOptionsFactory<T extends BuildOptions = BuildOptions> = (loadCache: LoadResultCache | undefined) => T;
@@ -6,9 +6,13 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
9
12
  Object.defineProperty(exports, "__esModule", { value: true });
10
13
  exports.BundlerContext = exports.BuildOutputFileType = void 0;
11
14
  const esbuild_1 = require("esbuild");
15
+ const node_assert_1 = __importDefault(require("node:assert"));
12
16
  const node_path_1 = require("node:path");
13
17
  const load_result_cache_1 = require("./load-result-cache");
14
18
  const utils_1 = require("./utils");
@@ -71,6 +75,7 @@ class BundlerContext {
71
75
  const externalImportsBrowser = new Set();
72
76
  const externalImportsServer = new Set();
73
77
  const outputFiles = [];
78
+ let externalConfiguration;
74
79
  for (const result of individualResults) {
75
80
  warnings.push(...result.warnings);
76
81
  if (result.errors) {
@@ -87,6 +92,12 @@ class BundlerContext {
87
92
  outputFiles.push(...result.outputFiles);
88
93
  result.externalImports.browser?.forEach((value) => externalImportsBrowser.add(value));
89
94
  result.externalImports.server?.forEach((value) => externalImportsServer.add(value));
95
+ if (result.externalConfiguration) {
96
+ externalConfiguration ??= new Set();
97
+ for (const value of result.externalConfiguration) {
98
+ externalConfiguration.add(value);
99
+ }
100
+ }
90
101
  }
91
102
  if (errors !== undefined) {
92
103
  return { errors, warnings };
@@ -101,6 +112,7 @@ class BundlerContext {
101
112
  browser: externalImportsBrowser,
102
113
  server: externalImportsServer,
103
114
  },
115
+ externalConfiguration: externalConfiguration ? [...externalConfiguration] : undefined,
104
116
  };
105
117
  }
106
118
  /**
@@ -250,10 +262,13 @@ class BundlerContext {
250
262
  externalImports.add(importData.path);
251
263
  }
252
264
  }
253
- const platformIsServer = this.#esbuildOptions?.platform === 'node';
265
+ (0, node_assert_1.default)(this.#esbuildOptions, 'esbuild options cannot be undefined.');
266
+ const { platform, assetNames = '' } = this.#esbuildOptions;
267
+ const platformIsServer = platform === 'node';
268
+ const mediaDirname = (0, node_path_1.dirname)(assetNames);
254
269
  const outputFiles = result.outputFiles.map((file) => {
255
270
  let fileType;
256
- if ((0, node_path_1.dirname)(file.path) === 'media') {
271
+ if ((0, node_path_1.dirname)(file.path) === mediaDirname) {
257
272
  fileType = BuildOutputFileType.Media;
258
273
  }
259
274
  else {
@@ -269,6 +284,7 @@ class BundlerContext {
269
284
  externalImports: {
270
285
  [platformIsServer ? 'server' : 'browser']: externalImports,
271
286
  },
287
+ externalConfiguration: this.#esbuildOptions.external,
272
288
  errors: undefined,
273
289
  };
274
290
  }
@@ -32,7 +32,7 @@ function createCompilerPluginOptions(options, target, sourceFileCache) {
32
32
  // Hidden component stylesheet sourcemaps are inaccessible which is effectively
33
33
  // the same as being disabled. Disabling has the advantage of avoiding the overhead
34
34
  // of sourcemap processing.
35
- !!sourcemapOptions.styles && (sourcemapOptions.hidden ? false : 'inline'),
35
+ sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
36
36
  outputNames,
37
37
  includePaths: stylePreprocessorOptions?.includePaths,
38
38
  externalDependencies,
@@ -45,7 +45,7 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
45
45
  const hints = [];
46
46
  const { indexHtmlOptions, externalPackages, optimizationOptions, crossOrigin, subresourceIntegrity, baseHref, } = buildOptions;
47
47
  (0, node_assert_1.default)(indexHtmlOptions, 'indexHtmlOptions cannot be undefined.');
48
- if (!externalPackages) {
48
+ if (!externalPackages && indexHtmlOptions.preloadInitial) {
49
49
  for (const [key, value] of initialFiles) {
50
50
  if (value.entrypoint) {
51
51
  // Entry points are already referenced in the HTML
@@ -87,6 +87,7 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
87
87
  },
88
88
  crossOrigin: crossOrigin,
89
89
  deployUrl: buildOptions.publicPath,
90
+ postTransform: indexHtmlOptions.transformer,
90
91
  });
91
92
  indexHtmlGenerator.readAsset = readAsset;
92
93
  const transformResult = await indexHtmlGenerator.process({
@@ -110,6 +111,7 @@ async function generateIndexHtml(initialFiles, outputFiles, buildOptions, lang)
110
111
  const { InlineCriticalCssProcessor } = await Promise.resolve().then(() => __importStar(require('../../utils/index-file/inline-critical-css')));
111
112
  const inlineCriticalCssProcessor = new InlineCriticalCssProcessor({
112
113
  minify: false, // CSS has already been minified during the build.
114
+ deployUrl: buildOptions.publicPath,
113
115
  readAsset,
114
116
  });
115
117
  const { content, errors, warnings } = await inlineCriticalCssProcessor.process(contentWithoutCriticalCssInlined, {
@@ -13,7 +13,7 @@ export interface BundleStylesheetOptions {
13
13
  optimization: boolean;
14
14
  inlineFonts: boolean;
15
15
  preserveSymlinks?: boolean;
16
- sourcemap: boolean | 'external' | 'inline';
16
+ sourcemap: boolean | 'external' | 'inline' | 'linked';
17
17
  outputNames: {
18
18
  bundles: string;
19
19
  media: string;
@@ -49,7 +49,15 @@ let postcss;
49
49
  *
50
50
  * Based on https://tailwindcss.com/docs/functions-and-directives
51
51
  */
52
- const TAILWIND_KEYWORDS = ['@tailwind', '@layer', '@apply', '@config', 'theme(', 'screen('];
52
+ const TAILWIND_KEYWORDS = [
53
+ '@tailwind',
54
+ '@layer',
55
+ '@apply',
56
+ '@config',
57
+ 'theme(',
58
+ 'screen(',
59
+ '@screen', // Undocumented in version 3, see: https://github.com/tailwindlabs/tailwindcss/discussions/7516.
60
+ ];
53
61
  /**
54
62
  * Cached postcss instances that can be re-used between various StylesheetPluginFactory instances.
55
63
  */
@@ -7,6 +7,7 @@
7
7
  */
8
8
  import { BuilderContext } from '@angular-devkit/architect';
9
9
  import { BuildOptions, Metafile, OutputFile, PartialMessage } from 'esbuild';
10
+ import { NormalizedOutputOptions } from '../../builders/application/options';
10
11
  import { BudgetCalculatorResult } from '../../utils/bundle-calculator';
11
12
  import { BuildOutputFile, BuildOutputFileType, InitialFileRecord } from './bundler-context';
12
13
  import { BuildOutputAsset } from './bundler-execution-result';
@@ -25,12 +26,11 @@ export declare function logMessages(context: BuilderContext, { errors, warnings
25
26
  * @returns An object that can be used with the esbuild build `supported` option.
26
27
  */
27
28
  export declare function getFeatureSupport(target: string[]): BuildOptions['supported'];
28
- export declare function writeResultFiles(outputFiles: BuildOutputFile[], assetFiles: BuildOutputAsset[] | undefined, outputPath: string): Promise<void>;
29
+ export declare function writeResultFiles(outputFiles: BuildOutputFile[], assetFiles: BuildOutputAsset[] | undefined, { base, browser, media, server }: NormalizedOutputOptions): Promise<void>;
29
30
  export declare function emitFilesToDisk<T = BuildOutputAsset | BuildOutputFile>(files: T[], writeFileCallback: (file: T) => Promise<void>): Promise<void>;
30
31
  export declare function createOutputFileFromText(path: string, text: string, type: BuildOutputFileType): BuildOutputFile;
31
32
  export declare function createOutputFileFromData(path: string, data: Uint8Array, type: BuildOutputFileType): BuildOutputFile;
32
33
  export declare function convertOutputFile(file: OutputFile, type: BuildOutputFileType): BuildOutputFile;
33
- export declare function getFullOutputPath(file: BuildOutputFile): string;
34
34
  /**
35
35
  * Transform browserlists result to esbuild target.
36
36
  * @see https://esbuild.github.io/api/#target