@angular/build 19.0.0-next.9 → 19.0.0-rc.1

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 (90) hide show
  1. package/package.json +21 -19
  2. package/src/builders/application/build-action.js +22 -10
  3. package/src/builders/application/chunk-optimizer.js +1 -4
  4. package/src/builders/application/execute-build.js +59 -24
  5. package/src/builders/application/execute-post-bundle.js +28 -5
  6. package/src/builders/application/index.d.ts +0 -16
  7. package/src/builders/application/index.js +15 -10
  8. package/src/builders/application/options.d.ts +14 -2
  9. package/src/builders/application/options.js +25 -10
  10. package/src/builders/application/results.d.ts +5 -3
  11. package/src/builders/application/schema.d.ts +86 -0
  12. package/src/builders/application/schema.js +19 -1
  13. package/src/builders/application/schema.json +73 -4
  14. package/src/builders/application/setup-bundling.d.ts +6 -1
  15. package/src/builders/application/setup-bundling.js +47 -13
  16. package/src/builders/dev-server/options.d.ts +2 -2
  17. package/src/builders/dev-server/options.js +2 -2
  18. package/src/builders/dev-server/schema.d.ts +2 -1
  19. package/src/builders/dev-server/schema.json +1 -2
  20. package/src/builders/dev-server/vite-server.d.ts +3 -2
  21. package/src/builders/dev-server/vite-server.js +123 -61
  22. package/src/index.d.ts +1 -0
  23. package/src/tools/angular/angular-host.d.ts +1 -1
  24. package/src/tools/angular/angular-host.js +14 -6
  25. package/src/tools/angular/compilation/angular-compilation.d.ts +1 -0
  26. package/src/tools/angular/compilation/aot-compilation.d.ts +1 -0
  27. package/src/tools/angular/compilation/aot-compilation.js +39 -0
  28. package/src/tools/angular/compilation/parallel-compilation.js +2 -2
  29. package/src/tools/angular/compilation/parallel-worker.d.ts +1 -0
  30. package/src/tools/angular/compilation/parallel-worker.js +5 -2
  31. package/src/tools/esbuild/angular/compiler-plugin.d.ts +3 -4
  32. package/src/tools/esbuild/angular/compiler-plugin.js +58 -33
  33. package/src/tools/esbuild/angular/component-stylesheets.d.ts +18 -18
  34. package/src/tools/esbuild/angular/component-stylesheets.js +66 -38
  35. package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
  36. package/src/tools/esbuild/angular/jit-plugin-callbacks.js +11 -3
  37. package/src/tools/esbuild/angular/source-file-cache.d.ts +1 -1
  38. package/src/tools/esbuild/angular/source-file-cache.js +6 -2
  39. package/src/tools/esbuild/application-code-bundle.d.ts +7 -5
  40. package/src/tools/esbuild/application-code-bundle.js +280 -249
  41. package/src/tools/esbuild/bundler-context.d.ts +2 -1
  42. package/src/tools/esbuild/bundler-context.js +10 -12
  43. package/src/tools/esbuild/bundler-execution-result.d.ts +14 -3
  44. package/src/tools/esbuild/bundler-execution-result.js +15 -8
  45. package/src/tools/esbuild/commonjs-checker.js +2 -2
  46. package/src/tools/esbuild/compiler-plugin-options.d.ts +2 -4
  47. package/src/tools/esbuild/compiler-plugin-options.js +15 -37
  48. package/src/tools/esbuild/global-scripts.js +1 -1
  49. package/src/tools/esbuild/global-styles.js +4 -1
  50. package/src/tools/esbuild/index-html-generator.js +8 -0
  51. package/src/tools/esbuild/javascript-transformer.js +3 -0
  52. package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
  53. package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
  54. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  55. package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
  56. package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
  57. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
  58. package/src/tools/esbuild/utils.js +13 -31
  59. package/src/tools/sass/worker.js +19 -0
  60. package/src/tools/vite/middlewares/assets-middleware.d.ts +6 -1
  61. package/src/tools/vite/middlewares/assets-middleware.js +42 -22
  62. package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
  63. package/src/tools/vite/middlewares/component-middleware.js +33 -0
  64. package/src/tools/vite/middlewares/index.d.ts +2 -1
  65. package/src/tools/vite/middlewares/index.js +3 -1
  66. package/src/tools/vite/middlewares/ssr-middleware.js +11 -8
  67. package/src/tools/vite/plugins/angular-memory-plugin.d.ts +1 -0
  68. package/src/tools/vite/plugins/angular-memory-plugin.js +5 -13
  69. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +3 -1
  70. package/src/tools/vite/plugins/setup-middlewares-plugin.js +12 -3
  71. package/src/tools/vite/utils.d.ts +1 -0
  72. package/src/typings.d.ts +1 -1
  73. package/src/utils/environment-options.d.ts +1 -0
  74. package/src/utils/environment-options.js +4 -2
  75. package/src/utils/index-file/auto-csp.d.ts +23 -0
  76. package/src/utils/index-file/auto-csp.js +283 -0
  77. package/src/utils/index-file/html-rewriting-stream.d.ts +5 -1
  78. package/src/utils/index-file/index-html-generator.d.ts +4 -0
  79. package/src/utils/index-file/index-html-generator.js +11 -0
  80. package/src/utils/index-file/inline-critical-css.js +17 -18
  81. package/src/utils/normalize-cache.js +1 -1
  82. package/src/utils/server-rendering/esm-in-memory-loader/utils.d.ts +8 -0
  83. package/src/utils/server-rendering/esm-in-memory-loader/utils.js +13 -0
  84. package/src/utils/server-rendering/launch-server.js +5 -5
  85. package/src/utils/server-rendering/load-esm-from-memory.d.ts +1 -1
  86. package/src/utils/server-rendering/manifest.d.ts +9 -8
  87. package/src/utils/server-rendering/manifest.js +17 -23
  88. package/src/utils/server-rendering/prerender.js +30 -19
  89. package/src/utils/server-rendering/render-worker.js +4 -2
  90. package/src/utils/supported-browsers.js +1 -0
@@ -43,11 +43,10 @@ const javascript_transformer_1 = require("../javascript-transformer");
43
43
  const load_result_cache_1 = require("../load-result-cache");
44
44
  const profiling_1 = require("../profiling");
45
45
  const compilation_state_1 = require("./compilation-state");
46
- const component_stylesheets_1 = require("./component-stylesheets");
47
46
  const file_reference_tracker_1 = require("./file-reference-tracker");
48
47
  const jit_plugin_callbacks_1 = require("./jit-plugin-callbacks");
49
48
  // eslint-disable-next-line max-lines-per-function
50
- function createCompilerPlugin(pluginOptions, styleOptions) {
49
+ function createCompilerPlugin(pluginOptions, stylesheetBundler) {
51
50
  return {
52
51
  name: 'angular-compiler',
53
52
  // eslint-disable-next-line max-lines-per-function
@@ -101,8 +100,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
101
100
  let shouldTsIgnoreJs = true;
102
101
  // Determines if transpilation should be handle by TypeScript or esbuild
103
102
  let useTypeScriptTranspilation = true;
104
- // Track incremental component stylesheet builds
105
- const stylesheetBundler = new component_stylesheets_1.ComponentStylesheetBundler(styleOptions, pluginOptions.incremental);
106
103
  let sharedTSCompilationState;
107
104
  // To fully invalidate files, track resource referenced files and their referencing source
108
105
  const referencedFileTracker = new file_reference_tracker_1.FileReferenceTracker();
@@ -121,14 +118,17 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
121
118
  // Angular compiler which does not have direct knowledge of transitive resource
122
119
  // dependencies or web worker processing.
123
120
  let modifiedFiles;
124
- let invalidatedStylesheetEntries;
125
121
  if (pluginOptions.sourceFileCache?.modifiedFiles.size &&
126
122
  referencedFileTracker &&
127
123
  !pluginOptions.noopTypeScriptCompilation) {
128
124
  // TODO: Differentiate between changed input files and stale output files
129
125
  modifiedFiles = referencedFileTracker.update(pluginOptions.sourceFileCache.modifiedFiles);
130
126
  pluginOptions.sourceFileCache.invalidate(modifiedFiles);
131
- invalidatedStylesheetEntries = stylesheetBundler.invalidate(modifiedFiles);
127
+ // External runtime styles are invalidated and rebuilt at the beginning of a rebuild to avoid
128
+ // the need to execute the application bundler for component style only changes.
129
+ if (!pluginOptions.externalRuntimeStyles) {
130
+ stylesheetBundler.invalidate(modifiedFiles);
131
+ }
132
132
  }
133
133
  if (!pluginOptions.noopTypeScriptCompilation &&
134
134
  compilation.update &&
@@ -140,7 +140,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
140
140
  fileReplacements: pluginOptions.fileReplacements,
141
141
  modifiedFiles,
142
142
  sourceFileCache: pluginOptions.sourceFileCache,
143
- async transformStylesheet(data, containingFile, stylesheetFile, order) {
143
+ async transformStylesheet(data, containingFile, stylesheetFile, order, className) {
144
144
  let stylesheetResult;
145
145
  // Stylesheet file only exists for external stylesheets
146
146
  if (stylesheetFile) {
@@ -148,8 +148,8 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
148
148
  }
149
149
  else {
150
150
  stylesheetResult = await stylesheetBundler.bundleInline(data, containingFile,
151
- // Inline stylesheets from a template style element are always CSS
152
- containingFile.endsWith('.html') ? 'css' : styleOptions.inlineStyleLanguage,
151
+ // Inline stylesheets from a template style element are always CSS; Otherwise, use default.
152
+ containingFile.endsWith('.html') ? 'css' : undefined,
153
153
  // When external runtime styles are enabled, an identifier for the style that does not change
154
154
  // based on the content is required to avoid emitted JS code changes. Any JS code changes will
155
155
  // invalid the output and force a full page reload for HMR cases. The containing file and order
@@ -158,14 +158,16 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
158
158
  ? (0, node_crypto_1.createHash)('sha-256')
159
159
  .update(containingFile)
160
160
  .update((order ?? 0).toString())
161
+ .update(className ?? '')
161
162
  .digest('hex')
162
163
  : undefined);
163
164
  }
164
- const { contents, outputFiles, metafile, referencedFiles, errors, warnings } = stylesheetResult;
165
- if (errors) {
166
- (result.errors ??= []).push(...errors);
165
+ (result.warnings ??= []).push(...stylesheetResult.warnings);
166
+ if (stylesheetResult.errors) {
167
+ (result.errors ??= []).push(...stylesheetResult.errors);
168
+ return '';
167
169
  }
168
- (result.warnings ??= []).push(...warnings);
170
+ const { contents, outputFiles, metafile, referencedFiles } = stylesheetResult;
169
171
  additionalResults.set(stylesheetFile ?? containingFile, {
170
172
  outputFiles,
171
173
  metafile,
@@ -215,7 +217,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
215
217
  let referencedFiles;
216
218
  let externalStylesheets;
217
219
  try {
218
- const initializationResult = await compilation.initialize(pluginOptions.tsconfig, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks));
220
+ const initializationResult = await compilation.initialize(pluginOptions.tsconfig, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks, build.initialOptions.conditions));
219
221
  shouldTsIgnoreJs = !initializationResult.compilerOptions.allowJs;
220
222
  // Isolated modules option ensures safe non-TypeScript transpilation.
221
223
  // Typescript printing support for sourcemaps is not yet integrated.
@@ -225,6 +227,10 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
225
227
  !!initializationResult.compilerOptions.inlineSourceMap;
226
228
  referencedFiles = initializationResult.referencedFiles;
227
229
  externalStylesheets = initializationResult.externalStylesheets;
230
+ if (initializationResult.templateUpdates) {
231
+ // Propagate any template updates
232
+ initializationResult.templateUpdates.forEach((value, key) => pluginOptions.templateUpdates?.set(key, value));
233
+ }
228
234
  }
229
235
  catch (error) {
230
236
  (result.errors ??= []).push({
@@ -250,13 +256,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
250
256
  for (const [stylesheetFile, externalId] of externalStylesheets) {
251
257
  await bundleExternalStylesheet(stylesheetBundler, stylesheetFile, externalId, result, additionalResults);
252
258
  }
253
- // Process any updated stylesheets
254
- if (invalidatedStylesheetEntries) {
255
- for (const stylesheetFile of invalidatedStylesheetEntries) {
256
- // externalId is already linked in the bundler context so only enabling is required here
257
- await bundleExternalStylesheet(stylesheetBundler, stylesheetFile, true, result, additionalResults);
258
- }
259
- }
260
259
  }
261
260
  // Update TypeScript file output cache for all affected files
262
261
  try {
@@ -344,9 +343,22 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
344
343
  // Store as the returned Uint8Array to allow caching the fully transformed code
345
344
  typeScriptFileCache.set(request, contents);
346
345
  }
346
+ let loader;
347
+ if (useTypeScriptTranspilation || isJS) {
348
+ // TypeScript has transpiled to JS or is already JS
349
+ loader = 'js';
350
+ }
351
+ else if (request.at(-1) === 'x') {
352
+ // TSX and TS have different syntax rules. Only set if input is a TSX file.
353
+ loader = 'tsx';
354
+ }
355
+ else {
356
+ // Otherwise, directly bundle TS
357
+ loader = 'ts';
358
+ }
347
359
  return {
348
360
  contents,
349
- loader: useTypeScriptTranspilation || isJS ? 'js' : 'ts',
361
+ loader,
350
362
  };
351
363
  });
352
364
  build.onLoad({ filter: /\.[cm]?js$/ }, (0, load_result_cache_1.createCachedLoad)(pluginOptions.loadResultCache, async (args) => {
@@ -361,7 +373,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
361
373
  }));
362
374
  // Setup bundling of component templates and stylesheets when in JIT mode
363
375
  if (pluginOptions.jit) {
364
- (0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage, pluginOptions.loadResultCache);
376
+ (0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, pluginOptions.loadResultCache);
365
377
  }
366
378
  build.onEnd((result) => {
367
379
  // Ensure other compilations are unblocked if the main compilation throws during start
@@ -384,7 +396,6 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
384
396
  });
385
397
  build.onDispose(() => {
386
398
  sharedTSCompilationState?.dispose();
387
- void stylesheetBundler.dispose();
388
399
  void compilation.close?.();
389
400
  void cacheStore?.close();
390
401
  });
@@ -405,17 +416,25 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
405
416
  };
406
417
  }
407
418
  async function bundleExternalStylesheet(stylesheetBundler, stylesheetFile, externalId, result, additionalResults) {
408
- const { outputFiles, metafile, errors, warnings } = await stylesheetBundler.bundleFile(stylesheetFile, externalId);
409
- if (errors) {
410
- (result.errors ??= []).push(...errors);
419
+ const styleResult = await stylesheetBundler.bundleFile(stylesheetFile, externalId);
420
+ (result.warnings ??= []).push(...styleResult.warnings);
421
+ if (styleResult.errors) {
422
+ (result.errors ??= []).push(...styleResult.errors);
423
+ }
424
+ else {
425
+ const { outputFiles, metafile } = styleResult;
426
+ // Clear inputs to prevent triggering a rebuild of the application code for component
427
+ // stylesheet file only changes when the dev server enables the internal-only external
428
+ // stylesheet option. This does not affect builds since only the dev server can enable
429
+ // the internal option.
430
+ metafile.inputs = {};
431
+ additionalResults.set(stylesheetFile, {
432
+ outputFiles,
433
+ metafile,
434
+ });
411
435
  }
412
- (result.warnings ??= []).push(...warnings);
413
- additionalResults.set(stylesheetFile, {
414
- outputFiles,
415
- metafile,
416
- });
417
436
  }
418
- function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks) {
437
+ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks, customConditions) {
419
438
  return (compilerOptions) => {
420
439
  // target of 9 is ES2022 (using the number avoids an expensive import of typescript just for an enum)
421
440
  if (compilerOptions.target === undefined || compilerOptions.target < 9 /** ES2022 */) {
@@ -463,6 +482,11 @@ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserve
463
482
  notes: [{ text: `The 'module' option will be set to 'ES2022' instead.` }],
464
483
  });
465
484
  }
485
+ // Synchronize custom resolve conditions.
486
+ // Set if using the supported bundler resolution mode (bundler is the default in new projects)
487
+ if (compilerOptions.moduleResolution === 100 /* ModuleResolutionKind.Bundler */) {
488
+ compilerOptions.customConditions = customConditions;
489
+ }
466
490
  return {
467
491
  ...compilerOptions,
468
492
  noEmitOnError: false,
@@ -473,6 +497,7 @@ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserve
473
497
  sourceRoot: undefined,
474
498
  preserveSymlinks,
475
499
  externalRuntimeStyles: pluginOptions.externalRuntimeStyles,
500
+ _enableHmr: !!pluginOptions.templateUpdates,
476
501
  };
477
502
  };
478
503
  }
@@ -5,8 +5,12 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.dev/license
7
7
  */
8
- import { OutputFile } from 'esbuild';
8
+ import { BundleContextResult } from '../bundler-context';
9
9
  import { BundleStylesheetOptions } from '../stylesheets/bundle-options';
10
+ export type ComponentStylesheetResult = BundleContextResult & {
11
+ contents: string;
12
+ referencedFiles: Set<string> | undefined;
13
+ };
10
14
  /**
11
15
  * Bundles component stylesheets. A stylesheet can be either an inline stylesheet that
12
16
  * is contained within the Component's metadata definition or an external file referenced
@@ -15,35 +19,31 @@ import { BundleStylesheetOptions } from '../stylesheets/bundle-options';
15
19
  export declare class ComponentStylesheetBundler {
16
20
  #private;
17
21
  private readonly options;
22
+ private readonly defaultInlineLanguage;
18
23
  private readonly incremental;
19
24
  /**
20
25
  *
21
26
  * @param options An object containing the stylesheet bundling options.
22
27
  * @param cache A load result cache to use when bundling.
23
28
  */
24
- constructor(options: BundleStylesheetOptions, incremental: boolean);
25
- bundleFile(entry: string, externalId?: string | boolean): Promise<{
26
- errors: import("esbuild").Message[] | undefined;
27
- warnings: import("esbuild").Message[];
28
- contents: string;
29
- outputFiles: OutputFile[];
30
- metafile: import("esbuild").Metafile | undefined;
31
- referencedFiles: Set<string> | undefined;
32
- }>;
33
- bundleInline(data: string, filename: string, language: string, externalId?: string): Promise<{
34
- errors: import("esbuild").Message[] | undefined;
35
- warnings: import("esbuild").Message[];
36
- contents: string;
37
- outputFiles: OutputFile[];
38
- metafile: import("esbuild").Metafile | undefined;
39
- referencedFiles: Set<string> | undefined;
40
- }>;
29
+ constructor(options: BundleStylesheetOptions, defaultInlineLanguage: string, incremental: boolean);
30
+ /**
31
+ * Bundle a file-based component stylesheet for use within an AOT compiled Angular application.
32
+ * @param entry The file path of the stylesheet.
33
+ * @param externalId Either an external identifier string for initial bundling or a boolean for rebuilds, if external.
34
+ * @param direct If true, the output will be used directly by the builder; false if used inside the compiler plugin.
35
+ * @returns A component bundle result object.
36
+ */
37
+ bundleFile(entry: string, externalId?: string | boolean, direct?: boolean): Promise<ComponentStylesheetResult>;
38
+ bundleAllFiles(external: boolean, direct: boolean): Promise<ComponentStylesheetResult[]>;
39
+ bundleInline(data: string, filename: string, language?: string, externalId?: string): Promise<ComponentStylesheetResult>;
41
40
  /**
42
41
  * Invalidates both file and inline based component style bundling state for a set of modified files.
43
42
  * @param files The group of files that have been modified
44
43
  * @returns An array of file based stylesheet entries if any were invalidated; otherwise, undefined.
45
44
  */
46
45
  invalidate(files: Iterable<string>): string[] | undefined;
46
+ collectReferencedFiles(): string[];
47
47
  dispose(): Promise<void>;
48
48
  private extractResult;
49
49
  }
@@ -24,6 +24,7 @@ const bundle_options_1 = require("../stylesheets/bundle-options");
24
24
  */
25
25
  class ComponentStylesheetBundler {
26
26
  options;
27
+ defaultInlineLanguage;
27
28
  incremental;
28
29
  #fileContexts = new cache_1.MemoryCache();
29
30
  #inlineContexts = new cache_1.MemoryCache();
@@ -32,17 +33,26 @@ class ComponentStylesheetBundler {
32
33
  * @param options An object containing the stylesheet bundling options.
33
34
  * @param cache A load result cache to use when bundling.
34
35
  */
35
- constructor(options, incremental) {
36
+ constructor(options, defaultInlineLanguage, incremental) {
36
37
  this.options = options;
38
+ this.defaultInlineLanguage = defaultInlineLanguage;
37
39
  this.incremental = incremental;
38
40
  }
39
- async bundleFile(entry, externalId) {
41
+ /**
42
+ * Bundle a file-based component stylesheet for use within an AOT compiled Angular application.
43
+ * @param entry The file path of the stylesheet.
44
+ * @param externalId Either an external identifier string for initial bundling or a boolean for rebuilds, if external.
45
+ * @param direct If true, the output will be used directly by the builder; false if used inside the compiler plugin.
46
+ * @returns A component bundle result object.
47
+ */
48
+ async bundleFile(entry, externalId, direct) {
40
49
  const bundlerContext = await this.#fileContexts.getOrCreate(entry, () => {
41
50
  return new bundler_context_1.BundlerContext(this.options.workspaceRoot, this.incremental, (loadCache) => {
42
51
  const buildOptions = (0, bundle_options_1.createStylesheetBundleOptions)(this.options, loadCache);
43
52
  if (externalId) {
44
53
  (0, node_assert_1.default)(typeof externalId === 'string', 'Initial external component stylesheets must have a string identifier');
45
54
  buildOptions.entryPoints = { [externalId]: entry };
55
+ buildOptions.entryNames = '[name]';
46
56
  delete buildOptions.publicPath;
47
57
  }
48
58
  else {
@@ -51,9 +61,12 @@ class ComponentStylesheetBundler {
51
61
  return buildOptions;
52
62
  });
53
63
  });
54
- return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles, !!externalId);
64
+ return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles, !!externalId, !!direct);
55
65
  }
56
- async bundleInline(data, filename, language, externalId) {
66
+ bundleAllFiles(external, direct) {
67
+ return Promise.all(Array.from(this.#fileContexts.entries()).map(([entry]) => this.bundleFile(entry, external, direct)));
68
+ }
69
+ async bundleInline(data, filename, language = this.defaultInlineLanguage, externalId) {
57
70
  // Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve
58
71
  // to the actual stylesheet file path.
59
72
  // TODO: Consider xxhash instead for hashing
@@ -70,6 +83,7 @@ class ComponentStylesheetBundler {
70
83
  });
71
84
  if (externalId) {
72
85
  buildOptions.entryPoints = { [externalId]: `${namespace};${entry}` };
86
+ buildOptions.entryNames = '[name]';
73
87
  delete buildOptions.publicPath;
74
88
  }
75
89
  else {
@@ -100,7 +114,7 @@ class ComponentStylesheetBundler {
100
114
  });
101
115
  });
102
116
  // Extract the result of the bundling from the output files
103
- return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles, !!externalId);
117
+ return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles, !!externalId, false);
104
118
  }
105
119
  /**
106
120
  * Invalidates both file and inline based component style bundling state for a set of modified files.
@@ -124,61 +138,75 @@ class ComponentStylesheetBundler {
124
138
  }
125
139
  return entries;
126
140
  }
141
+ collectReferencedFiles() {
142
+ const files = [];
143
+ for (const context of this.#fileContexts.values()) {
144
+ files.push(...context.watchFiles);
145
+ }
146
+ return files;
147
+ }
127
148
  async dispose() {
128
149
  const contexts = [...this.#fileContexts.values(), ...this.#inlineContexts.values()];
129
150
  this.#fileContexts.clear();
130
151
  this.#inlineContexts.clear();
131
152
  await Promise.allSettled(contexts.map((context) => context.dispose()));
132
153
  }
133
- extractResult(result, referencedFiles, external) {
154
+ extractResult(result, referencedFiles, external, direct) {
134
155
  let contents = '';
135
- let metafile;
136
156
  const outputFiles = [];
137
- if (!result.errors) {
138
- for (const outputFile of result.outputFiles) {
139
- const filename = node_path_1.default.basename(outputFile.path);
140
- if (outputFile.type === bundler_context_1.BuildOutputFileType.Media || filename.endsWith('.css.map')) {
141
- // The output files could also contain resources (images/fonts/etc.) that were referenced and the map files.
142
- // Clone the output file to avoid amending the original path which would causes problems during rebuild.
143
- const clonedOutputFile = outputFile.clone();
144
- // Needed for Bazel as otherwise the files will not be written in the correct place,
145
- // this is because esbuild will resolve the output file from the outdir which is currently set to `workspaceRoot` twice,
146
- // once in the stylesheet and the other in the application code bundler.
147
- // Ex: `../../../../../app.component.css.map`.
157
+ const { errors, warnings } = result;
158
+ if (errors) {
159
+ return { errors, warnings, referencedFiles, contents: '' };
160
+ }
161
+ for (const outputFile of result.outputFiles) {
162
+ const filename = node_path_1.default.basename(outputFile.path);
163
+ if (outputFile.type === bundler_context_1.BuildOutputFileType.Media || filename.endsWith('.css.map')) {
164
+ // The output files could also contain resources (images/fonts/etc.) that were referenced and the map files.
165
+ // Clone the output file to avoid amending the original path which would causes problems during rebuild.
166
+ const clonedOutputFile = outputFile.clone();
167
+ // Needed for Bazel as otherwise the files will not be written in the correct place,
168
+ // this is because esbuild will resolve the output file from the outdir which is currently set to `workspaceRoot` twice,
169
+ // once in the stylesheet and the other in the application code bundler.
170
+ // Ex: `../../../../../app.component.css.map`.
171
+ if (!direct) {
148
172
  clonedOutputFile.path = node_path_1.default.join(this.options.workspaceRoot, outputFile.path);
149
- outputFiles.push(clonedOutputFile);
150
173
  }
151
- else if (filename.endsWith('.css')) {
152
- if (external) {
153
- const clonedOutputFile = outputFile.clone();
174
+ outputFiles.push(clonedOutputFile);
175
+ }
176
+ else if (filename.endsWith('.css')) {
177
+ if (external) {
178
+ const clonedOutputFile = outputFile.clone();
179
+ if (!direct) {
154
180
  clonedOutputFile.path = node_path_1.default.join(this.options.workspaceRoot, outputFile.path);
155
- outputFiles.push(clonedOutputFile);
156
- contents = node_path_1.default.posix.join(this.options.publicPath ?? '', filename);
157
- }
158
- else {
159
- contents = outputFile.text;
160
181
  }
182
+ outputFiles.push(clonedOutputFile);
183
+ contents = node_path_1.default.posix.join(this.options.publicPath ?? '', filename);
161
184
  }
162
185
  else {
163
- throw new Error(`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`);
186
+ contents = outputFile.text;
164
187
  }
165
188
  }
166
- metafile = result.metafile;
167
- // Remove entryPoint fields from outputs to prevent the internal component styles from being
168
- // treated as initial files. Also mark the entry as a component resource for stat reporting.
169
- Object.values(metafile.outputs).forEach((output) => {
170
- delete output.entryPoint;
171
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
- output['ng-component'] = true;
173
- });
189
+ else {
190
+ throw new Error(`Unexpected non CSS/Media file "${filename}" outputted during component stylesheet processing.`);
191
+ }
174
192
  }
193
+ const metafile = result.metafile;
194
+ // Remove entryPoint fields from outputs to prevent the internal component styles from being
195
+ // treated as initial files. Also mark the entry as a component resource for stat reporting.
196
+ Object.values(metafile.outputs).forEach((output) => {
197
+ delete output.entryPoint;
198
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
199
+ output['ng-component'] = true;
200
+ });
175
201
  return {
176
- errors: result.errors,
177
- warnings: result.warnings,
202
+ errors,
203
+ warnings,
178
204
  contents,
179
205
  outputFiles,
180
206
  metafile,
181
207
  referencedFiles,
208
+ externalImports: result.externalImports,
209
+ initialFiles: new Map(),
182
210
  };
183
211
  }
184
212
  }
@@ -20,4 +20,4 @@ import { ComponentStylesheetBundler } from './component-stylesheets';
20
20
  export declare function setupJitPluginCallbacks(build: PluginBuild, stylesheetBundler: ComponentStylesheetBundler, additionalResultFiles: Map<string, {
21
21
  outputFiles?: OutputFile[];
22
22
  metafile?: Metafile;
23
- }>, inlineStyleLanguage: string, loadCache?: LoadResultCache): void;
23
+ }>, loadCache?: LoadResultCache): void;
@@ -51,7 +51,7 @@ async function loadEntry(entry, root, skipRead) {
51
51
  * @param styleOptions The options to use when bundling stylesheets.
52
52
  * @param additionalResultFiles A Map where stylesheet resources will be added.
53
53
  */
54
- function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles, inlineStyleLanguage, loadCache) {
54
+ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles, loadCache) {
55
55
  const root = build.initialOptions.absWorkingDir ?? '';
56
56
  // Add a resolve callback to capture and parse any JIT URIs that were added by the
57
57
  // JIT resource TypeScript transformer.
@@ -90,9 +90,17 @@ function setupJitPluginCallbacks(build, stylesheetBundler, additionalResultFiles
90
90
  stylesheetResult = await stylesheetBundler.bundleFile(entry.path);
91
91
  }
92
92
  else {
93
- stylesheetResult = await stylesheetBundler.bundleInline(entry.contents, entry.path, inlineStyleLanguage);
93
+ stylesheetResult = await stylesheetBundler.bundleInline(entry.contents, entry.path);
94
94
  }
95
- const { contents, outputFiles, errors, warnings, metafile, referencedFiles } = stylesheetResult;
95
+ const { errors, warnings, referencedFiles } = stylesheetResult;
96
+ if (stylesheetResult.errors) {
97
+ return {
98
+ errors,
99
+ warnings,
100
+ watchFiles: referencedFiles && [...referencedFiles],
101
+ };
102
+ }
103
+ const { contents, outputFiles, metafile } = stylesheetResult;
96
104
  additionalResultFiles.set(entry.path, { outputFiles, metafile });
97
105
  return {
98
106
  errors,
@@ -14,5 +14,5 @@ export declare class SourceFileCache extends Map<string, ts.SourceFile> {
14
14
  readonly loadResultCache: MemoryLoadResultCache;
15
15
  referencedFiles?: readonly string[];
16
16
  constructor(persistentCachePath?: string | undefined);
17
- invalidate(files: Iterable<string>): void;
17
+ invalidate(files: Iterable<string>): boolean;
18
18
  }
@@ -50,16 +50,20 @@ class SourceFileCache extends Map {
50
50
  if (files !== this.modifiedFiles) {
51
51
  this.modifiedFiles.clear();
52
52
  }
53
+ const extraWatchFiles = new Set(this.referencedFiles?.map(path.normalize));
54
+ let invalid = false;
53
55
  for (let file of files) {
54
56
  file = path.normalize(file);
55
- this.loadResultCache.invalidate(file);
57
+ invalid = this.loadResultCache.invalidate(file) || invalid;
58
+ invalid = extraWatchFiles.has(file) || invalid;
56
59
  // Normalize separators to allow matching TypeScript Host paths
57
60
  if (USING_WINDOWS) {
58
61
  file = file.replace(WINDOWS_SEP_REGEXP, path.posix.sep);
59
62
  }
60
- this.delete(file);
63
+ invalid = this.delete(file) || invalid;
61
64
  this.modifiedFiles.add(file);
62
65
  }
66
+ return invalid;
63
67
  }
64
68
  }
65
69
  exports.SourceFileCache = SourceFileCache;
@@ -7,10 +7,12 @@
7
7
  */
8
8
  import type { BuildOptions } from 'esbuild';
9
9
  import type { NormalizedApplicationBuildOptions } from '../../builders/application/options';
10
+ import { ComponentStylesheetBundler } from './angular/component-stylesheets';
10
11
  import { SourceFileCache } from './angular/source-file-cache';
11
12
  import { BundlerOptionsFactory } from './bundler-context';
12
- export declare function createBrowserCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions;
13
- export declare function createBrowserPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BuildOptions | BundlerOptionsFactory | undefined;
14
- export declare function createServerPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache?: SourceFileCache): BundlerOptionsFactory | undefined;
15
- export declare function createServerMainCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;
16
- export declare function createSsrEntryCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache): BuildOptions;
13
+ import type { LoadResultCache } from './load-result-cache';
14
+ export declare function createBrowserCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler, templateUpdates: Map<string, string> | undefined): BundlerOptionsFactory;
15
+ export declare function createBrowserPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler): BuildOptions | BundlerOptionsFactory | undefined;
16
+ export declare function createServerPolyfillBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], loadResultCache: LoadResultCache | undefined): BundlerOptionsFactory | undefined;
17
+ export declare function createServerMainCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler): BundlerOptionsFactory;
18
+ export declare function createSsrEntryCodeBundleOptions(options: NormalizedApplicationBuildOptions, target: string[], sourceFileCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler): BundlerOptionsFactory;