From 296ea8f7f63d86e405c01e012667306e4a77d9a2 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 31 Oct 2024 14:25:54 -0400 Subject: [PATCH] refactor(@angular/build): allow experimental template update generation via environment variable The experimental Angular component template hot replacement capabilities will be initially controlled via an environment variable. Setting `NG_HMR_TEMPLATES=1` with the development server that is using the application builder will generate the runtime event code to support hot replacement of an individual component template. The build system itself does not yet generate the component update build results needed to trigger the runtime events. The environment variable is currently intended to support integration of the remaining code to fully implement the feature. (cherry picked from commit 5c2aa2f4b15b7ccfe3da0d5db3a04a81dbafe209) --- .../angular/build/src/builders/application/options.ts | 8 ++++++++ .../build/src/builders/dev-server/vite-server.ts | 10 +++++++++- .../build/src/tools/esbuild/angular/compiler-plugin.ts | 2 ++ .../build/src/tools/esbuild/compiler-plugin-options.ts | 2 ++ .../angular/build/src/utils/environment-options.ts | 4 ++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/angular/build/src/builders/application/options.ts b/packages/angular/build/src/builders/application/options.ts index df34c1cbe510..dcac17d97d1e 100644 --- a/packages/angular/build/src/builders/application/options.ts +++ b/packages/angular/build/src/builders/application/options.ts @@ -98,6 +98,13 @@ interface InternalOptions { */ externalRuntimeStyles?: boolean; + /** + * Enables the AOT compiler to generate template component update functions. + * This option is only intended to be used with a development server that can process and serve component + * template updates. + */ + templateUpdates?: boolean; + /** * Enables instrumentation to collect code coverage data for specific files. * @@ -463,6 +470,7 @@ export async function normalizeOptions( externalRuntimeStyles, instrumentForCoverage, security, + templateUpdates: !!options.templateUpdates, }; } diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index f909d7ea4c32..a7a5d5a27e1a 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -23,7 +23,7 @@ import { createRemoveIdPrefixPlugin, } from '../../tools/vite/plugins'; import { loadProxyConfiguration, normalizeSourceMaps } from '../../utils'; -import { useComponentStyleHmr } from '../../utils/environment-options'; +import { useComponentStyleHmr, useComponentTemplateHmr } from '../../utils/environment-options'; import { loadEsmModule } from '../../utils/load-esm'; import { Result, ResultFile, ResultKind } from '../application/results'; import { @@ -145,6 +145,14 @@ export async function* serveWithVite( void loadEsmModule('@angular/compiler'); } + // Enable to support component template hot replacement (`NG_HMR_TEMPLATE=1` can be used to enable) + browserOptions.templateUpdates = !!serverOptions.liveReload && useComponentTemplateHmr; + if (browserOptions.templateUpdates) { + context.logger.warn( + 'Experimental support for component template hot replacement has been enabled via the "NG_HMR_TEMPLATE" environment variable.', + ); + } + // Setup the prebundling transformer that will be shared across Vite prebundling requests const prebundleTransformer = new JavaScriptTransformer( // Always enable JIT linking to support applications built with and without AOT. diff --git a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts index 7f838e50307e..b4f5db4435c5 100644 --- a/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts +++ b/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts @@ -51,6 +51,7 @@ export interface CompilerPluginOptions { incremental: boolean; externalRuntimeStyles?: boolean; instrumentForCoverage?: (request: string) => boolean; + templateUpdates?: boolean; } // eslint-disable-next-line max-lines-per-function @@ -656,6 +657,7 @@ function createCompilerOptionsTransformer( sourceRoot: undefined, preserveSymlinks, externalRuntimeStyles: pluginOptions.externalRuntimeStyles, + _enableHmr: pluginOptions.templateUpdates, }; }; } diff --git a/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts b/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts index 192a7a142acf..7f8e496a3383 100644 --- a/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts +++ b/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts @@ -25,6 +25,7 @@ export function createCompilerPluginOptions( jit, externalRuntimeStyles, instrumentForCoverage, + templateUpdates, } = options; const incremental = !!options.watch; @@ -40,5 +41,6 @@ export function createCompilerPluginOptions( incremental, externalRuntimeStyles, instrumentForCoverage, + templateUpdates, }; } diff --git a/packages/angular/build/src/utils/environment-options.ts b/packages/angular/build/src/utils/environment-options.ts index 73e403b7f171..40de16a535e3 100644 --- a/packages/angular/build/src/utils/environment-options.ts +++ b/packages/angular/build/src/utils/environment-options.ts @@ -105,6 +105,10 @@ const hmrComponentStylesVariable = process.env['NG_HMR_CSTYLES']; export const useComponentStyleHmr = !isPresent(hmrComponentStylesVariable) || !isDisabled(hmrComponentStylesVariable); +const hmrComponentTemplateVariable = process.env['NG_HMR_TEMPLATES']; +export const useComponentTemplateHmr = + isPresent(hmrComponentTemplateVariable) && isEnabled(hmrComponentTemplateVariable); + const partialSsrBuildVariable = process.env['NG_BUILD_PARTIAL_SSR']; export const usePartialSsrBuild = isPresent(partialSsrBuildVariable) && isEnabled(partialSsrBuildVariable);