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

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 (55) hide show
  1. package/package.json +13 -13
  2. package/src/builders/application/execute-build.js +14 -6
  3. package/src/builders/application/options.d.ts +3 -1
  4. package/src/builders/application/options.js +2 -1
  5. package/src/builders/application/results.d.ts +5 -3
  6. package/src/builders/application/schema.d.ts +57 -0
  7. package/src/builders/application/schema.js +19 -1
  8. package/src/builders/application/schema.json +33 -0
  9. package/src/builders/application/setup-bundling.d.ts +3 -1
  10. package/src/builders/application/setup-bundling.js +33 -6
  11. package/src/builders/dev-server/vite-server.d.ts +1 -1
  12. package/src/builders/dev-server/vite-server.js +26 -7
  13. package/src/tools/angular/angular-host.d.ts +1 -1
  14. package/src/tools/angular/angular-host.js +1 -4
  15. package/src/tools/angular/compilation/parallel-compilation.js +2 -2
  16. package/src/tools/angular/compilation/parallel-worker.js +3 -1
  17. package/src/tools/esbuild/angular/compiler-plugin.d.ts +2 -4
  18. package/src/tools/esbuild/angular/compiler-plugin.js +27 -12
  19. package/src/tools/esbuild/angular/component-stylesheets.d.ts +3 -2
  20. package/src/tools/esbuild/angular/component-stylesheets.js +4 -2
  21. package/src/tools/esbuild/angular/jit-plugin-callbacks.d.ts +1 -1
  22. package/src/tools/esbuild/angular/jit-plugin-callbacks.js +2 -2
  23. package/src/tools/esbuild/application-code-bundle.d.ts +5 -4
  24. package/src/tools/esbuild/application-code-bundle.js +61 -40
  25. package/src/tools/esbuild/bundler-context.js +7 -10
  26. package/src/tools/esbuild/bundler-execution-result.d.ts +5 -2
  27. package/src/tools/esbuild/bundler-execution-result.js +5 -1
  28. package/src/tools/esbuild/compiler-plugin-options.d.ts +1 -4
  29. package/src/tools/esbuild/compiler-plugin-options.js +14 -37
  30. package/src/tools/esbuild/global-scripts.js +1 -1
  31. package/src/tools/esbuild/global-styles.js +3 -0
  32. package/src/tools/esbuild/server-bundle-metadata-plugin.d.ts +22 -0
  33. package/src/tools/esbuild/server-bundle-metadata-plugin.js +36 -0
  34. package/src/tools/esbuild/stylesheets/bundle-options.d.ts +2 -0
  35. package/src/tools/esbuild/stylesheets/bundle-options.js +2 -1
  36. package/src/tools/esbuild/stylesheets/sass-language.js +4 -0
  37. package/src/tools/esbuild/stylesheets/stylesheet-plugin-factory.d.ts +9 -0
  38. package/src/tools/esbuild/utils.js +12 -1
  39. package/src/tools/sass/worker.js +19 -0
  40. package/src/tools/vite/middlewares/assets-middleware.d.ts +1 -1
  41. package/src/tools/vite/middlewares/assets-middleware.js +3 -3
  42. package/src/tools/vite/middlewares/component-middleware.d.ts +9 -0
  43. package/src/tools/vite/middlewares/component-middleware.js +33 -0
  44. package/src/tools/vite/middlewares/index.d.ts +1 -0
  45. package/src/tools/vite/middlewares/index.js +3 -1
  46. package/src/tools/vite/middlewares/ssr-middleware.js +6 -6
  47. package/src/tools/vite/plugins/setup-middlewares-plugin.d.ts +2 -1
  48. package/src/tools/vite/plugins/setup-middlewares-plugin.js +2 -1
  49. package/src/utils/environment-options.js +1 -1
  50. package/src/utils/index-file/html-rewriting-stream.d.ts +5 -1
  51. package/src/utils/normalize-cache.js +1 -1
  52. package/src/utils/server-rendering/launch-server.js +5 -5
  53. package/src/utils/server-rendering/load-esm-from-memory.d.ts +1 -1
  54. package/src/utils/server-rendering/manifest.d.ts +1 -1
  55. 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.12",
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.12",
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.80.3",
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.12",
61
61
  "less": "^4.2.0",
62
62
  "postcss": "^8.4.0",
63
63
  "tailwindcss": "^2.0.0 || ^3.0.0",
@@ -41,17 +41,25 @@ async function executeBuild(options, context, rebuildState) {
41
41
  await (0, i18n_1.loadActiveTranslations)(context, i18nOptions);
42
42
  }
43
43
  // Reuse rebuild state or create new bundle contexts for code and global stylesheets
44
- let bundlerContexts = rebuildState?.rebuildContexts;
45
- const codeBundleCache = rebuildState?.codeBundleCache ??
46
- new source_file_cache_1.SourceFileCache(cacheOptions.enabled ? cacheOptions.path : undefined);
47
- if (bundlerContexts === undefined) {
48
- bundlerContexts = (0, setup_bundling_1.setupBundlerContexts)(options, browsers, codeBundleCache);
44
+ let bundlerContexts;
45
+ let componentStyleBundler;
46
+ let codeBundleCache;
47
+ if (rebuildState) {
48
+ bundlerContexts = rebuildState.rebuildContexts;
49
+ componentStyleBundler = rebuildState.componentStyleBundler;
50
+ codeBundleCache = rebuildState.codeBundleCache;
51
+ }
52
+ else {
53
+ const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
54
+ codeBundleCache = new source_file_cache_1.SourceFileCache(cacheOptions.enabled ? cacheOptions.path : undefined);
55
+ componentStyleBundler = (0, setup_bundling_1.createComponentStyleBundler)(options, target);
56
+ bundlerContexts = (0, setup_bundling_1.setupBundlerContexts)(options, target, codeBundleCache, componentStyleBundler);
49
57
  }
50
58
  let bundlingResult = await bundler_context_1.BundlerContext.bundleAll(bundlerContexts, rebuildState?.fileChanges.all);
51
59
  if (options.optimizationOptions.scripts && environment_options_1.shouldOptimizeChunks) {
52
60
  bundlingResult = await (0, profiling_1.profileAsync)('OPTIMIZE_CHUNKS', () => (0, chunk_optimizer_1.optimizeChunks)(bundlingResult, options.sourcemapOptions.scripts ? !options.sourcemapOptions.hidden || 'hidden' : false));
53
61
  }
54
- const executionResult = new bundler_execution_result_1.ExecutionResult(bundlerContexts, codeBundleCache);
62
+ const executionResult = new bundler_execution_result_1.ExecutionResult(bundlerContexts, componentStyleBundler, codeBundleCache);
55
63
  executionResult.addWarnings(bundlingResult.warnings);
56
64
  // Return if the bundling has errors
57
65
  if (bundlingResult.errors) {
@@ -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
@@ -5,6 +5,7 @@
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 { ComponentStylesheetBundler } from '../../tools/esbuild/angular/component-stylesheets';
8
9
  import { SourceFileCache } from '../../tools/esbuild/angular/source-file-cache';
9
10
  import { BundlerContext } from '../../tools/esbuild/bundler-context';
10
11
  import { NormalizedApplicationBuildOptions } from './options';
@@ -16,4 +17,5 @@ import { NormalizedApplicationBuildOptions } from './options';
16
17
  * @param codeBundleCache An instance of the TypeScript source file cache.
17
18
  * @returns An array of BundlerContext objects.
18
19
  */
19
- export declare function setupBundlerContexts(options: NormalizedApplicationBuildOptions, browsers: string[], codeBundleCache: SourceFileCache): BundlerContext[];
20
+ export declare function setupBundlerContexts(options: NormalizedApplicationBuildOptions, target: string[], codeBundleCache: SourceFileCache, stylesheetBundler: ComponentStylesheetBundler): BundlerContext[];
21
+ export declare function createComponentStyleBundler(options: NormalizedApplicationBuildOptions, target: string[]): ComponentStylesheetBundler;
@@ -8,6 +8,8 @@
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.setupBundlerContexts = setupBundlerContexts;
11
+ exports.createComponentStyleBundler = createComponentStyleBundler;
12
+ const component_stylesheets_1 = require("../../tools/esbuild/angular/component-stylesheets");
11
13
  const application_code_bundle_1 = require("../../tools/esbuild/application-code-bundle");
12
14
  const bundler_context_1 = require("../../tools/esbuild/bundler-context");
13
15
  const global_scripts_1 = require("../../tools/esbuild/global-scripts");
@@ -21,14 +23,13 @@ const utils_1 = require("../../tools/esbuild/utils");
21
23
  * @param codeBundleCache An instance of the TypeScript source file cache.
22
24
  * @returns An array of BundlerContext objects.
23
25
  */
24
- function setupBundlerContexts(options, browsers, codeBundleCache) {
26
+ function setupBundlerContexts(options, target, codeBundleCache, stylesheetBundler) {
25
27
  const { outputMode, serverEntryPoint, appShellOptions, prerenderOptions, ssrOptions, workspaceRoot, watch = false, } = options;
26
- const target = (0, utils_1.transformSupportedBrowsersToTargets)(browsers);
27
28
  const bundlerContexts = [];
28
29
  // Browser application code
29
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache)));
30
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createBrowserCodeBundleOptions)(options, target, codeBundleCache, stylesheetBundler)));
30
31
  // Browser polyfills code
31
- const browserPolyfillBundleOptions = (0, application_code_bundle_1.createBrowserPolyfillBundleOptions)(options, target, codeBundleCache);
32
+ const browserPolyfillBundleOptions = (0, application_code_bundle_1.createBrowserPolyfillBundleOptions)(options, target, codeBundleCache, stylesheetBundler);
32
33
  if (browserPolyfillBundleOptions) {
33
34
  bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, browserPolyfillBundleOptions));
34
35
  }
@@ -53,10 +54,10 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
53
54
  // Skip server build when none of the features are enabled.
54
55
  if (serverEntryPoint && (outputMode || prerenderOptions || appShellOptions || ssrOptions)) {
55
56
  const nodeTargets = [...target, ...(0, utils_1.getSupportedNodeTargets)()];
56
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createServerMainCodeBundleOptions)(options, nodeTargets, codeBundleCache)));
57
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createServerMainCodeBundleOptions)(options, nodeTargets, codeBundleCache, stylesheetBundler)));
57
58
  if (outputMode && ssrOptions?.entry) {
58
59
  // New behavior introduced: 'server.ts' is now bundled separately from 'main.server.ts'.
59
- bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createSsrEntryCodeBundleOptions)(options, nodeTargets, codeBundleCache)));
60
+ bundlerContexts.push(new bundler_context_1.BundlerContext(workspaceRoot, watch, (0, application_code_bundle_1.createSsrEntryCodeBundleOptions)(options, nodeTargets, codeBundleCache, stylesheetBundler)));
60
61
  }
61
62
  // Server polyfills code
62
63
  const serverPolyfillBundleOptions = (0, application_code_bundle_1.createServerPolyfillBundleOptions)(options, nodeTargets, codeBundleCache);
@@ -66,3 +67,29 @@ function setupBundlerContexts(options, browsers, codeBundleCache) {
66
67
  }
67
68
  return bundlerContexts;
68
69
  }
70
+ function createComponentStyleBundler(options, target) {
71
+ const { workspaceRoot, optimizationOptions, sourcemapOptions, outputNames, externalDependencies, preserveSymlinks, stylePreprocessorOptions, inlineStyleLanguage, cacheOptions, tailwindConfiguration, postcssConfiguration, publicPath, } = options;
72
+ const incremental = !!options.watch;
73
+ return new component_stylesheets_1.ComponentStylesheetBundler({
74
+ workspaceRoot,
75
+ inlineFonts: !!optimizationOptions.fonts.inline,
76
+ optimization: !!optimizationOptions.styles.minify,
77
+ sourcemap:
78
+ // Hidden component stylesheet sourcemaps are inaccessible which is effectively
79
+ // the same as being disabled. Disabling has the advantage of avoiding the overhead
80
+ // of sourcemap processing.
81
+ sourcemapOptions.styles && !sourcemapOptions.hidden ? 'linked' : false,
82
+ outputNames,
83
+ includePaths: stylePreprocessorOptions?.includePaths,
84
+ // string[] | undefined' is not assignable to type '(Version | DeprecationOrId)[] | undefined'.
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ sass: stylePreprocessorOptions?.sass,
87
+ externalDependencies,
88
+ target,
89
+ preserveSymlinks,
90
+ tailwindConfiguration,
91
+ postcssConfiguration,
92
+ cacheOptions,
93
+ publicPath,
94
+ }, inlineStyleLanguage, incremental);
95
+ }
@@ -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
  },
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import type { Plugin } from 'esbuild';
9
9
  import { LoadResultCache } from '../load-result-cache';
10
- import { BundleStylesheetOptions } from '../stylesheets/bundle-options';
10
+ import { ComponentStylesheetBundler } from './component-stylesheets';
11
11
  import { SourceFileCache } from './source-file-cache';
12
12
  export interface CompilerPluginOptions {
13
13
  sourcemap: boolean | 'external';
@@ -24,6 +24,4 @@ export interface CompilerPluginOptions {
24
24
  externalRuntimeStyles?: boolean;
25
25
  instrumentForCoverage?: (request: string) => boolean;
26
26
  }
27
- export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, styleOptions: BundleStylesheetOptions & {
28
- inlineStyleLanguage: string;
29
- }): Plugin;
27
+ export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, stylesheetBundler: ComponentStylesheetBundler): Plugin;