@angular/build 19.0.0-next.10 → 19.0.0-next.11

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 (45) hide show
  1. package/package.json +13 -13
  2. package/src/builders/application/options.d.ts +3 -1
  3. package/src/builders/application/options.js +2 -1
  4. package/src/builders/application/results.d.ts +5 -3
  5. package/src/builders/application/schema.d.ts +57 -0
  6. package/src/builders/application/schema.js +19 -1
  7. package/src/builders/application/schema.json +33 -0
  8. package/src/builders/dev-server/vite-server.d.ts +1 -1
  9. package/src/builders/dev-server/vite-server.js +26 -7
  10. package/src/tools/angular/angular-host.d.ts +1 -1
  11. package/src/tools/angular/angular-host.js +1 -4
  12. package/src/tools/angular/compilation/parallel-compilation.js +2 -2
  13. package/src/tools/angular/compilation/parallel-worker.js +3 -1
  14. package/src/tools/esbuild/angular/compiler-plugin.js +27 -8
  15. package/src/tools/esbuild/angular/component-stylesheets.d.ts +3 -2
  16. package/src/tools/esbuild/angular/component-stylesheets.js +4 -2
  17. package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
  18. package/src/tools/esbuild/angular/jit-plugin-callbacks.js +2 -2
  19. package/src/tools/esbuild/application-code-bundle.js +46 -25
  20. package/src/tools/esbuild/bundler-context.js +7 -10
  21. package/src/tools/esbuild/compiler-plugin-options.js +3 -0
  22. package/src/tools/esbuild/global-scripts.js +1 -1
  23. package/src/tools/esbuild/global-styles.js +3 -0
  24. package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
  25. package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
  26. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  27. package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
  28. package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
  29. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
  30. package/src/tools/esbuild/utils.js +12 -1
  31. package/src/tools/sass/worker.js +19 -0
  32. package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
  33. package/src/tools/vite/middlewares/assets-middleware.js +2 -2
  34. package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
  35. package/src/tools/vite/middlewares/component-middleware.js +33 -0
  36. package/src/tools/vite/middlewares/index.d.ts +1 -0
  37. package/src/tools/vite/middlewares/index.js +3 -1
  38. package/src/tools/vite/middlewares/ssr-middleware.js +6 -6
  39. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +2 -1
  40. package/src/tools/vite/plugins/setup-middlewares-plugin.js +2 -1
  41. package/src/utils/environment-options.js +1 -1
  42. package/src/utils/normalize-cache.js +1 -1
  43. package/src/utils/server-rendering/launch-server.js +5 -5
  44. package/src/utils/server-rendering/load-esm-from-memory.d.ts +1 -1
  45. package/src/utils/supported-browsers.js +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/build",
3
- "version": "19.0.0-next.10",
3
+ "version": "19.0.0-next.11",
4
4
  "description": "Official build system for Angular",
5
5
  "keywords": [
6
6
  "Angular CLI",
@@ -23,41 +23,41 @@
23
23
  "builders": "builders.json",
24
24
  "dependencies": {
25
25
  "@ampproject/remapping": "2.3.0",
26
- "@angular-devkit/architect": "0.1900.0-next.10",
27
- "@babel/core": "7.25.7",
26
+ "@angular-devkit/architect": "0.1900.0-next.11",
27
+ "@babel/core": "7.25.8",
28
28
  "@babel/helper-annotate-as-pure": "7.25.7",
29
29
  "@babel/helper-split-export-declaration": "7.24.7",
30
30
  "@babel/plugin-syntax-import-attributes": "7.25.7",
31
31
  "@inquirer/confirm": "5.0.0",
32
32
  "@vitejs/plugin-basic-ssl": "1.1.0",
33
33
  "browserslist": "^4.23.0",
34
- "critters": "0.0.24",
34
+ "critters": "0.0.25",
35
35
  "esbuild": "0.24.0",
36
36
  "fast-glob": "3.3.2",
37
37
  "https-proxy-agent": "7.0.5",
38
38
  "istanbul-lib-instrument": "6.0.3",
39
39
  "listr2": "8.2.5",
40
- "magic-string": "0.30.11",
40
+ "magic-string": "0.30.12",
41
41
  "mrmime": "2.0.0",
42
42
  "parse5-html-rewriting-stream": "7.0.0",
43
43
  "picomatch": "4.0.2",
44
44
  "piscina": "4.7.0",
45
45
  "rollup": "4.24.0",
46
- "sass": "1.79.4",
46
+ "sass": "1.79.5",
47
47
  "semver": "7.6.3",
48
- "vite": "5.4.8",
48
+ "vite": "5.4.9",
49
49
  "watchpack": "2.4.2"
50
50
  },
51
51
  "optionalDependencies": {
52
52
  "lmdb": "3.1.3"
53
53
  },
54
54
  "peerDependencies": {
55
- "@angular/compiler": "^19.0.0-next.0",
56
- "@angular/compiler-cli": "^19.0.0-next.0",
57
- "@angular/localize": "^19.0.0-next.0",
58
- "@angular/platform-server": "^19.0.0-next.0",
59
- "@angular/service-worker": "^19.0.0-next.0",
60
- "@angular/ssr": "^19.0.0-next.10",
55
+ "@angular/compiler": "^19.0.0-next.9",
56
+ "@angular/compiler-cli": "^19.0.0-next.9",
57
+ "@angular/localize": "^19.0.0-next.9",
58
+ "@angular/platform-server": "^19.0.0-next.9",
59
+ "@angular/service-worker": "^19.0.0-next.9",
60
+ "@angular/ssr": "^19.0.0-next.11",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -9,7 +9,7 @@ import type { BuilderContext } from '@angular-devkit/architect';
9
9
  import type { Plugin } from 'esbuild';
10
10
  import { I18nOptions } from '../../utils/i18n-options';
11
11
  import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
12
- import { Schema as ApplicationBuilderOptions, I18NTranslation, OutputMode, OutputPathClass } from './schema';
12
+ import { Schema as ApplicationBuilderOptions, ExperimentalPlatform, I18NTranslation, OutputMode, OutputPathClass } from './schema';
13
13
  /**
14
14
  * The filename for the client-side rendered HTML template.
15
15
  * This template is used for client-side rendering (CSR) in a web application.
@@ -119,8 +119,10 @@ export declare function normalizeOptions(context: BuilderContext, projectName: s
119
119
  outputMode: OutputMode | undefined;
120
120
  ssrOptions: {
121
121
  entry?: undefined;
122
+ platform?: undefined;
122
123
  } | {
123
124
  entry: string | undefined;
125
+ platform: ExperimentalPlatform;
124
126
  } | undefined;
125
127
  verbose: boolean | undefined;
126
128
  watch: boolean | undefined;
@@ -153,9 +153,10 @@ async function normalizeOptions(context, projectName, options, extensions) {
153
153
  ssrOptions = {};
154
154
  }
155
155
  else if (typeof options.ssr === 'object') {
156
- const { entry } = options.ssr;
156
+ const { entry, experimentalPlatform = schema_1.ExperimentalPlatform.Node } = options.ssr;
157
157
  ssrOptions = {
158
158
  entry: entry && node_path_1.default.join(workspaceRoot, entry),
159
+ platform: experimentalPlatform,
159
160
  };
160
161
  }
161
162
  let appShellOptions;
@@ -61,7 +61,9 @@ export interface ResultMessage {
61
61
  }
62
62
  export interface ComponentUpdateResult extends BaseResult {
63
63
  kind: ResultKind.ComponentUpdate;
64
- id: string;
65
- type: 'style' | 'template';
66
- content: string;
64
+ updates: {
65
+ id: string;
66
+ type: 'style' | 'template';
67
+ content: string;
68
+ }[];
67
69
  }
@@ -500,6 +500,37 @@ export interface SsrClass {
500
500
  * The server entry-point that when executed will spawn the web server.
501
501
  */
502
502
  entry?: string;
503
+ /**
504
+ * Specifies the platform for which the server bundle is generated. This affects the APIs
505
+ * and modules available in the server-side code.
506
+ *
507
+ * - `node`: (Default) Generates a bundle optimized for Node.js environments.
508
+ * - `neutral`: Generates a platform-neutral bundle suitable for environments like edge
509
+ * workers, and other serverless platforms. This option avoids using Node.js-specific APIs,
510
+ * making the bundle more portable.
511
+ *
512
+ * Please note that this feature does not provide polyfills for Node.js modules.
513
+ * Additionally, it is experimental, and the schematics may undergo changes in future
514
+ * versions.
515
+ */
516
+ experimentalPlatform?: ExperimentalPlatform;
517
+ }
518
+ /**
519
+ * Specifies the platform for which the server bundle is generated. This affects the APIs
520
+ * and modules available in the server-side code.
521
+ *
522
+ * - `node`: (Default) Generates a bundle optimized for Node.js environments.
523
+ * - `neutral`: Generates a platform-neutral bundle suitable for environments like edge
524
+ * workers, and other serverless platforms. This option avoids using Node.js-specific APIs,
525
+ * making the bundle more portable.
526
+ *
527
+ * Please note that this feature does not provide polyfills for Node.js modules.
528
+ * Additionally, it is experimental, and the schematics may undergo changes in future
529
+ * versions.
530
+ */
531
+ export declare enum ExperimentalPlatform {
532
+ Neutral = "neutral",
533
+ Node = "node"
503
534
  }
504
535
  /**
505
536
  * Options to pass to style preprocessors.
@@ -509,6 +540,32 @@ export interface StylePreprocessorOptions {
509
540
  * Paths to include. Paths will be resolved to workspace root.
510
541
  */
511
542
  includePaths?: string[];
543
+ /**
544
+ * Options to pass to the sass preprocessor.
545
+ */
546
+ sass?: Sass;
547
+ }
548
+ /**
549
+ * Options to pass to the sass preprocessor.
550
+ */
551
+ export interface Sass {
552
+ /**
553
+ * A set of deprecations to treat as fatal. If a deprecation warning of any provided type is
554
+ * encountered during compilation, the compiler will error instead. If a Version is
555
+ * provided, then all deprecations that were active in that compiler version will be treated
556
+ * as fatal.
557
+ */
558
+ fatalDeprecations?: string[];
559
+ /**
560
+ * A set of future deprecations to opt into early. Future deprecations passed here will be
561
+ * treated as active by the compiler, emitting warnings as necessary.
562
+ */
563
+ futureDeprecations?: string[];
564
+ /**
565
+ * A set of active deprecations to ignore. If a deprecation warning of any provided type is
566
+ * encountered during compilation, the compiler will ignore it instead.
567
+ */
568
+ silenceDeprecations?: string[];
512
569
  }
513
570
  export type StyleElement = StyleClass | string;
514
571
  export interface StyleClass {
@@ -2,7 +2,7 @@
2
2
  // THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
3
3
  // CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.OutputMode = exports.OutputHashing = exports.InlineStyleLanguage = exports.I18NTranslation = exports.CrossOrigin = exports.Type = void 0;
5
+ exports.ExperimentalPlatform = exports.OutputMode = exports.OutputHashing = exports.InlineStyleLanguage = exports.I18NTranslation = exports.CrossOrigin = exports.Type = void 0;
6
6
  /**
7
7
  * The type of budget.
8
8
  */
@@ -66,3 +66,21 @@ var OutputMode;
66
66
  OutputMode["Server"] = "server";
67
67
  OutputMode["Static"] = "static";
68
68
  })(OutputMode || (exports.OutputMode = OutputMode = {}));
69
+ /**
70
+ * Specifies the platform for which the server bundle is generated. This affects the APIs
71
+ * and modules available in the server-side code.
72
+ *
73
+ * - `node`: (Default) Generates a bundle optimized for Node.js environments.
74
+ * - `neutral`: Generates a platform-neutral bundle suitable for environments like edge
75
+ * workers, and other serverless platforms. This option avoids using Node.js-specific APIs,
76
+ * making the bundle more portable.
77
+ *
78
+ * Please note that this feature does not provide polyfills for Node.js modules.
79
+ * Additionally, it is experimental, and the schematics may undergo changes in future
80
+ * versions.
81
+ */
82
+ var ExperimentalPlatform;
83
+ (function (ExperimentalPlatform) {
84
+ ExperimentalPlatform["Neutral"] = "neutral";
85
+ ExperimentalPlatform["Node"] = "node";
86
+ })(ExperimentalPlatform || (exports.ExperimentalPlatform = ExperimentalPlatform = {}));
@@ -125,6 +125,34 @@
125
125
  "type": "string"
126
126
  },
127
127
  "default": []
128
+ },
129
+ "sass": {
130
+ "description": "Options to pass to the sass preprocessor.",
131
+ "type": "object",
132
+ "properties": {
133
+ "fatalDeprecations": {
134
+ "description": "A set of deprecations to treat as fatal. If a deprecation warning of any provided type is encountered during compilation, the compiler will error instead. If a Version is provided, then all deprecations that were active in that compiler version will be treated as fatal.",
135
+ "type": "array",
136
+ "items": {
137
+ "type": "string"
138
+ }
139
+ },
140
+ "silenceDeprecations": {
141
+ "description": " A set of active deprecations to ignore. If a deprecation warning of any provided type is encountered during compilation, the compiler will ignore it instead.",
142
+ "type": "array",
143
+ "items": {
144
+ "type": "string"
145
+ }
146
+ },
147
+ "futureDeprecations": {
148
+ "description": "A set of future deprecations to opt into early. Future deprecations passed here will be treated as active by the compiler, emitting warnings as necessary.",
149
+ "type": "array",
150
+ "items": {
151
+ "type": "string"
152
+ }
153
+ }
154
+ },
155
+ "additionalProperties": false
128
156
  }
129
157
  },
130
158
  "additionalProperties": false
@@ -518,6 +546,11 @@
518
546
  "entry": {
519
547
  "type": "string",
520
548
  "description": "The server entry-point that when executed will spawn the web server."
549
+ },
550
+ "experimentalPlatform": {
551
+ "description": "Specifies the platform for which the server bundle is generated. This affects the APIs and modules available in the server-side code. \n\n- `node`: (Default) Generates a bundle optimized for Node.js environments. \n- `neutral`: Generates a platform-neutral bundle suitable for environments like edge workers, and other serverless platforms. This option avoids using Node.js-specific APIs, making the bundle more portable. \n\nPlease note that this feature does not provide polyfills for Node.js modules. Additionally, it is experimental, and the schematics may undergo changes in future versions.",
552
+ "default": "node",
553
+ "enum": ["node", "neutral"]
521
554
  }
522
555
  },
523
556
  "additionalProperties": false
@@ -32,6 +32,6 @@ export declare function serveWithVite(serverOptions: NormalizedDevServerOptions,
32
32
  middleware?: Connect.NextHandleFunction[];
33
33
  buildPlugins?: Plugin[];
34
34
  }): AsyncIterableIterator<DevServerBuilderOutput>;
35
- export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, usedComponentStyles: Map<string, string[]>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
35
+ export declare function setupServer(serverOptions: NormalizedDevServerOptions, outputFiles: Map<string, OutputFileRecord>, assets: Map<string, string>, preserveSymlinks: boolean | undefined, externalMetadata: DevServerExternalResultMetadata, ssrMode: ServerSsrMode, prebundleTransformer: JavaScriptTransformer, target: string[], zoneless: boolean, usedComponentStyles: Map<string, Set<string>>, templateUpdates: Map<string, string>, prebundleLoaderExtensions: EsbuildLoaderOption | undefined, extensionMiddleware?: Connect.NextHandleFunction[], indexHtmlTransformer?: (content: string) => Promise<string>, thirdPartySourcemaps?: boolean): Promise<InlineConfig>;
36
36
  type EsbuildLoaderOption = Exclude<DepOptimizationConfig['esbuildOptions'], undefined>['loader'];
37
37
  export {};
@@ -92,8 +92,13 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
92
92
  // https://nodejs.org/api/process.html#processsetsourcemapsenabledval
93
93
  process.setSourceMapsEnabled(true);
94
94
  }
95
- // TODO: Enable by default once full support across CLI and FW is integrated
96
- browserOptions.externalRuntimeStyles = environment_options_1.useComponentStyleHmr;
95
+ // Enable to support component style hot reloading (`NG_HMR_CSTYLES=0` can be used to disable)
96
+ browserOptions.externalRuntimeStyles = !!serverOptions.liveReload && environment_options_1.useComponentStyleHmr;
97
+ if (browserOptions.externalRuntimeStyles) {
98
+ // Preload the @angular/compiler package to avoid first stylesheet request delays.
99
+ // Once @angular/build is native ESM, this should be re-evaluated.
100
+ void (0, load_esm_1.loadEsmModule)('@angular/compiler');
101
+ }
97
102
  // Setup the prebundling transformer that will be shared across Vite prebundling requests
98
103
  const prebundleTransformer = new internal_1.JavaScriptTransformer(
99
104
  // Always enable JIT linking to support applications built with and without AOT.
@@ -116,6 +121,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
116
121
  explicitServer: [],
117
122
  };
118
123
  const usedComponentStyles = new Map();
124
+ const templateUpdates = new Map();
119
125
  // Add cleanup logic via a builder teardown.
120
126
  let deferred;
121
127
  context.addTeardown(async () => {
@@ -157,6 +163,8 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
157
163
  assetFiles.set('/' + normalizePath(outputPath), normalizePath(file.inputPath));
158
164
  }
159
165
  }
166
+ // Clear stale template updates on a code rebuilds
167
+ templateUpdates.clear();
160
168
  // Analyze result files for changes
161
169
  analyzeResultFiles(normalizePath, htmlIndexPath, result.files, generatedFiles);
162
170
  break;
@@ -166,8 +174,18 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
166
174
  break;
167
175
  case results_1.ResultKind.ComponentUpdate:
168
176
  (0, node_assert_1.default)(serverOptions.hmr, 'Component updates are only supported with HMR enabled.');
169
- // TODO: Implement support -- application builder currently does not use
170
- break;
177
+ (0, node_assert_1.default)(server, 'Builder must provide an initial full build before component update results.');
178
+ for (const componentUpdate of result.updates) {
179
+ if (componentUpdate.type === 'template') {
180
+ templateUpdates.set(componentUpdate.id, componentUpdate.content);
181
+ server.ws.send('angular:component-update', {
182
+ id: componentUpdate.id,
183
+ timestamp: Date.now(),
184
+ });
185
+ }
186
+ }
187
+ context.logger.info('Component update sent to client(s).');
188
+ continue;
171
189
  default:
172
190
  context.logger.warn(`Unknown result kind [${result.kind}] provided by build.`);
173
191
  continue;
@@ -259,7 +277,7 @@ async function* serveWithVite(serverOptions, builderName, builderAction, context
259
277
  });
260
278
  }
261
279
  // Setup server and start listening
262
- const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), usedComponentStyles, browserOptions.loader, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
280
+ const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles, browserOptions.preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, (0, internal_1.isZonelessApp)(polyfills), usedComponentStyles, templateUpdates, browserOptions.loader, extensions?.middleware, transformers?.indexHtml, thirdPartySourcemaps);
263
281
  server = await createServer(serverConfiguration);
264
282
  await server.listen();
265
283
  const urls = server.resolvedUrls;
@@ -328,7 +346,7 @@ async function handleUpdate(normalizePath, generatedFiles, server, serverOptions
328
346
  // are not typically reused across components.
329
347
  const componentIds = usedComponentStyles.get(filePath);
330
348
  if (componentIds) {
331
- return componentIds.map((id) => ({
349
+ return Array.from(componentIds).map((id) => ({
332
350
  type: 'css-update',
333
351
  timestamp,
334
352
  path: `${filePath}?ngcomp` + (id ? `=${id}` : ''),
@@ -409,7 +427,7 @@ function analyzeResultFiles(normalizePath, htmlIndexPath, resultFiles, generated
409
427
  }
410
428
  }
411
429
  }
412
- async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, zoneless, usedComponentStyles, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
430
+ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks, externalMetadata, ssrMode, prebundleTransformer, target, zoneless, usedComponentStyles, templateUpdates, prebundleLoaderExtensions, extensionMiddleware, indexHtmlTransformer, thirdPartySourcemaps = false) {
413
431
  const proxy = await (0, utils_1.loadProxyConfiguration)(serverOptions.workspaceRoot, serverOptions.proxyConfig);
414
432
  // dynamically import Vite for ESM compatibility
415
433
  const { normalizePath } = await (0, load_esm_1.loadEsmModule)('vite');
@@ -502,6 +520,7 @@ async function setupServer(serverOptions, outputFiles, assets, preserveSymlinks,
502
520
  indexHtmlTransformer,
503
521
  extensionMiddleware,
504
522
  usedComponentStyles,
523
+ templateUpdates,
505
524
  ssrMode,
506
525
  }),
507
526
  (0, plugins_1.createRemoveIdPrefixPlugin)(externalMetadata.explicitBrowser),
@@ -14,7 +14,7 @@ export interface AngularHostOptions {
14
14
  sourceFileCache?: Map<string, ts.SourceFile>;
15
15
  modifiedFiles?: Set<string>;
16
16
  externalStylesheets?: Map<string, string>;
17
- transformStylesheet(data: string, containingFile: string, stylesheetFile?: string, order?: number): Promise<string | null>;
17
+ transformStylesheet(data: string, containingFile: string, stylesheetFile?: string, order?: number, className?: string): Promise<string | null>;
18
18
  processWebWorker(workerFile: string, containingFile: string): string;
19
19
  }
20
20
  /**
@@ -113,10 +113,7 @@ function createAngularCompilerHost(typescript, compilerOptions, hostOptions) {
113
113
  if (data.trim().length === 0) {
114
114
  return { content: '' };
115
115
  }
116
- const result = await hostOptions.transformStylesheet(data, context.containingFile, context.resourceFile ?? undefined,
117
- // TODO: Remove once available in compiler-cli types
118
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
119
- context.order);
116
+ const result = await hostOptions.transformStylesheet(data, context.containingFile, context.resourceFile ?? undefined, context.order, context.className);
120
117
  return typeof result === 'string' ? { content: result } : null;
121
118
  };
122
119
  host.resourceNameToFileName = function (resourceName, containingFile) {
@@ -37,9 +37,9 @@ class ParallelCompilation extends angular_compilation_1.AngularCompilation {
37
37
  initialize(tsconfig, hostOptions, compilerOptionsTransformer) {
38
38
  const stylesheetChannel = new node_worker_threads_1.MessageChannel();
39
39
  // The request identifier is required because Angular can issue multiple concurrent requests
40
- stylesheetChannel.port1.on('message', ({ requestId, data, containingFile, stylesheetFile }) => {
40
+ stylesheetChannel.port1.on('message', ({ requestId, data, containingFile, stylesheetFile, order, className }) => {
41
41
  hostOptions
42
- .transformStylesheet(data, containingFile, stylesheetFile)
42
+ .transformStylesheet(data, containingFile, stylesheetFile, order, className)
43
43
  .then((value) => stylesheetChannel.port1.postMessage({ requestId, value }))
44
44
  .catch((error) => stylesheetChannel.port1.postMessage({ requestId, error }));
45
45
  });
@@ -37,7 +37,7 @@ async function initialize(request) {
37
37
  fileReplacements: request.fileReplacements,
38
38
  sourceFileCache,
39
39
  modifiedFiles: sourceFileCache.modifiedFiles,
40
- transformStylesheet(data, containingFile, stylesheetFile) {
40
+ transformStylesheet(data, containingFile, stylesheetFile, order, className) {
41
41
  const requestId = (0, node_crypto_1.randomUUID)();
42
42
  const resultPromise = new Promise((resolve, reject) => stylesheetRequests.set(requestId, [resolve, reject]));
43
43
  request.stylesheetPort.postMessage({
@@ -45,6 +45,8 @@ async function initialize(request) {
45
45
  data,
46
46
  containingFile,
47
47
  stylesheetFile,
48
+ order,
49
+ className,
48
50
  });
49
51
  return resultPromise;
50
52
  },
@@ -102,7 +102,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
102
102
  // Determines if transpilation should be handle by TypeScript or esbuild
103
103
  let useTypeScriptTranspilation = true;
104
104
  // Track incremental component stylesheet builds
105
- const stylesheetBundler = new component_stylesheets_1.ComponentStylesheetBundler(styleOptions, pluginOptions.incremental);
105
+ const stylesheetBundler = new component_stylesheets_1.ComponentStylesheetBundler(styleOptions, styleOptions.inlineStyleLanguage, pluginOptions.incremental);
106
106
  let sharedTSCompilationState;
107
107
  // To fully invalidate files, track resource referenced files and their referencing source
108
108
  const referencedFileTracker = new file_reference_tracker_1.FileReferenceTracker();
@@ -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,6 +158,7 @@ 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
  }
@@ -215,7 +216,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
215
216
  let referencedFiles;
216
217
  let externalStylesheets;
217
218
  try {
218
- const initializationResult = await compilation.initialize(pluginOptions.tsconfig, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks));
219
+ const initializationResult = await compilation.initialize(pluginOptions.tsconfig, hostOptions, createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks, build.initialOptions.conditions));
219
220
  shouldTsIgnoreJs = !initializationResult.compilerOptions.allowJs;
220
221
  // Isolated modules option ensures safe non-TypeScript transpilation.
221
222
  // Typescript printing support for sourcemaps is not yet integrated.
@@ -344,9 +345,22 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
344
345
  // Store as the returned Uint8Array to allow caching the fully transformed code
345
346
  typeScriptFileCache.set(request, contents);
346
347
  }
348
+ let loader;
349
+ if (useTypeScriptTranspilation || isJS) {
350
+ // TypeScript has transpiled to JS or is already JS
351
+ loader = 'js';
352
+ }
353
+ else if (request.at(-1) === 'x') {
354
+ // TSX and TS have different syntax rules. Only set if input is a TSX file.
355
+ loader = 'tsx';
356
+ }
357
+ else {
358
+ // Otherwise, directly bundle TS
359
+ loader = 'ts';
360
+ }
347
361
  return {
348
362
  contents,
349
- loader: useTypeScriptTranspilation || isJS ? 'js' : 'ts',
363
+ loader,
350
364
  };
351
365
  });
352
366
  build.onLoad({ filter: /\.[cm]?js$/ }, (0, load_result_cache_1.createCachedLoad)(pluginOptions.loadResultCache, async (args) => {
@@ -361,7 +375,7 @@ function createCompilerPlugin(pluginOptions, styleOptions) {
361
375
  }));
362
376
  // Setup bundling of component templates and stylesheets when in JIT mode
363
377
  if (pluginOptions.jit) {
364
- (0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, styleOptions.inlineStyleLanguage, pluginOptions.loadResultCache);
378
+ (0, jit_plugin_callbacks_1.setupJitPluginCallbacks)(build, stylesheetBundler, additionalResults, pluginOptions.loadResultCache);
365
379
  }
366
380
  build.onEnd((result) => {
367
381
  // Ensure other compilations are unblocked if the main compilation throws during start
@@ -415,7 +429,7 @@ async function bundleExternalStylesheet(stylesheetBundler, stylesheetFile, exter
415
429
  metafile,
416
430
  });
417
431
  }
418
- function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks) {
432
+ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserveSymlinks, customConditions) {
419
433
  return (compilerOptions) => {
420
434
  // target of 9 is ES2022 (using the number avoids an expensive import of typescript just for an enum)
421
435
  if (compilerOptions.target === undefined || compilerOptions.target < 9 /** ES2022 */) {
@@ -463,6 +477,11 @@ function createCompilerOptionsTransformer(setupWarnings, pluginOptions, preserve
463
477
  notes: [{ text: `The 'module' option will be set to 'ES2022' instead.` }],
464
478
  });
465
479
  }
480
+ // Synchronize custom resolve conditions.
481
+ // Set if using the supported bundler resolution mode (bundler is the default in new projects)
482
+ if (compilerOptions.moduleResolution === 100 /* ModuleResolutionKind.Bundler */) {
483
+ compilerOptions.customConditions = customConditions;
484
+ }
466
485
  return {
467
486
  ...compilerOptions,
468
487
  noEmitOnError: false,
@@ -15,13 +15,14 @@ import { BundleStylesheetOptions } from '../stylesheets/bundle-options';
15
15
  export declare class ComponentStylesheetBundler {
16
16
  #private;
17
17
  private readonly options;
18
+ private readonly defaultInlineLanguage;
18
19
  private readonly incremental;
19
20
  /**
20
21
  *
21
22
  * @param options An object containing the stylesheet bundling options.
22
23
  * @param cache A load result cache to use when bundling.
23
24
  */
24
- constructor(options: BundleStylesheetOptions, incremental: boolean);
25
+ constructor(options: BundleStylesheetOptions, defaultInlineLanguage: string, incremental: boolean);
25
26
  bundleFile(entry: string, externalId?: string | boolean): Promise<{
26
27
  errors: import("esbuild").Message[] | undefined;
27
28
  warnings: import("esbuild").Message[];
@@ -30,7 +31,7 @@ export declare class ComponentStylesheetBundler {
30
31
  metafile: import("esbuild").Metafile | undefined;
31
32
  referencedFiles: Set<string> | undefined;
32
33
  }>;
33
- bundleInline(data: string, filename: string, language: string, externalId?: string): Promise<{
34
+ bundleInline(data: string, filename: string, language?: string, externalId?: string): Promise<{
34
35
  errors: import("esbuild").Message[] | undefined;
35
36
  warnings: import("esbuild").Message[];
36
37
  contents: string;
@@ -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,8 +33,9 @@ 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
41
  async bundleFile(entry, externalId) {
@@ -53,7 +55,7 @@ class ComponentStylesheetBundler {
53
55
  });
54
56
  return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles, !!externalId);
55
57
  }
56
- async bundleInline(data, filename, language, externalId) {
58
+ async bundleInline(data, filename, language = this.defaultInlineLanguage, externalId) {
57
59
  // Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve
58
60
  // to the actual stylesheet file path.
59
61
  // TODO: Consider xxhash instead for hashing
@@ -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,7 +90,7 @@ 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
95
  const { contents, outputFiles, errors, warnings, metafile, referencedFiles } = stylesheetResult;
96
96
  additionalResultFiles.set(entry.path, { outputFiles, metafile });