Skip to content

Commit b1d6d2f

Browse files
committed
fix(@angular/build): resolve Angular locale data namespace in esbuild
A transient error can occur during `ng serve` when Vite's dependency pre-bundling is triggered for Angular locale data, showing an error like `[vite] (ssr) Error when evaluating SSR module...: There is a new version of the pre-bundle...`. Previously, the `angular:locale/data:` namespace was left unresolved by the build process for the dev server. This caused Vite to treat the namespace as a new dependency, triggering a pre-bundling step that led to the error. With this change, esbuild now resolves the `angular:locale/data:` namespace and replaces it with the direct module import path. While the module is still treated as an external dependency, providing the explicit path prevents Vite from unnecessarily triggering a new pre-bundling phase. This resolves the transient error. Closes #31498
1 parent 44d9539 commit b1d6d2f

File tree

4 files changed

+36
-84
lines changed

4 files changed

+36
-84
lines changed

packages/angular/build/src/builders/dev-server/vite/server.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type { Connect, InlineConfig, SSROptions, ServerOptions } from 'vite';
1212
import type { ComponentStyleRecord } from '../../../tools/vite/middlewares';
1313
import {
1414
ServerSsrMode,
15-
createAngularLocaleDataPlugin,
1615
createAngularMemoryPlugin,
1716
createAngularSetupMiddlewaresPlugin,
1817
createAngularSsrTransformPlugin,
@@ -221,7 +220,6 @@ export async function setupServer(
221220
define,
222221
),
223222
plugins: [
224-
createAngularLocaleDataPlugin(),
225223
createAngularSetupMiddlewaresPlugin({
226224
outputFiles,
227225
assets,

packages/angular/build/src/tools/esbuild/i18n-locale-plugin.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import type { Plugin } from 'esbuild';
9+
import type { Plugin, ResolveResult } from 'esbuild';
10+
import { createRequire } from 'node:module';
1011

1112
/**
1213
* The internal namespace used by generated locale import statements and Angular locale data plugin.
@@ -27,17 +28,6 @@ export function createAngularLocaleDataPlugin(): Plugin {
2728
return {
2829
name: 'angular-locale-data',
2930
setup(build): void {
30-
// If packages are configured to be external then leave the original angular locale import path.
31-
// This happens when using the development server with caching enabled to allow Vite prebundling to work.
32-
// There currently is no option on the esbuild resolve function to resolve while disabling the option. To
33-
// workaround the inability to resolve the full locale location here, the Vite dev server prebundling also
34-
// contains a plugin to allow the locales to be correctly resolved when prebundling.
35-
// NOTE: If esbuild eventually allows controlling the external package options in a build.resolve call, this
36-
// workaround can be removed.
37-
if (build.initialOptions.packages === 'external') {
38-
return;
39-
}
40-
4131
build.onResolve({ filter: /^angular:locale\/data:/ }, async ({ path }) => {
4232
// Extract the locale from the path
4333
const rawLocaleTag = path.split(':', 3)[2];
@@ -60,6 +50,7 @@ export function createAngularLocaleDataPlugin(): Plugin {
6050
}
6151

6252
let exact = true;
53+
let localeRequire: NodeJS.Require | undefined;
6354
while (partialLocaleTag) {
6455
// Angular embeds the `en`/`en-US` locale into the framework and it does not need to be included again here.
6556
// The onLoad hook below for the locale data namespace has an `empty` loader that will prevent inclusion.
@@ -73,11 +64,39 @@ export function createAngularLocaleDataPlugin(): Plugin {
7364

7465
// Attempt to resolve the locale tag data within the Angular base module location
7566
const potentialPath = `${LOCALE_DATA_BASE_MODULE}/${partialLocaleTag}`;
76-
const result = await build.resolve(potentialPath, {
77-
kind: 'import-statement',
78-
resolveDir: build.initialOptions.absWorkingDir,
79-
});
80-
if (result.path) {
67+
68+
// If packages are configured to be external then leave the original angular locale import path.
69+
// This happens when using the development server with caching enabled to allow Vite prebundling to work.
70+
// There currently is no option on the esbuild resolve function to resolve while disabling the option.
71+
// NOTE: If esbuild eventually allows controlling the external package options in a build.resolve call, this
72+
// workaround can be removed.
73+
let result: ResolveResult | undefined;
74+
const { packages, absWorkingDir } = build.initialOptions;
75+
if (packages === 'external' && absWorkingDir) {
76+
localeRequire ??= createRequire(absWorkingDir + '/');
77+
78+
try {
79+
localeRequire.resolve(potentialPath);
80+
81+
result = {
82+
errors: [],
83+
warnings: [],
84+
external: true,
85+
sideEffects: true,
86+
namespace: '',
87+
suffix: '',
88+
pluginData: undefined,
89+
path: potentialPath,
90+
};
91+
} catch {}
92+
} else {
93+
result = await build.resolve(potentialPath, {
94+
kind: 'import-statement',
95+
resolveDir: absWorkingDir,
96+
});
97+
}
98+
99+
if (result?.path) {
81100
if (exact) {
82101
return result;
83102
} else {

packages/angular/build/src/tools/vite/plugins/i18n-locale-plugin.ts

Lines changed: 0 additions & 64 deletions
This file was deleted.

packages/angular/build/src/tools/vite/plugins/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
*/
88

99
export { createAngularMemoryPlugin } from './angular-memory-plugin';
10-
export { createAngularLocaleDataPlugin } from './i18n-locale-plugin';
1110
export { createRemoveIdPrefixPlugin } from './id-prefix-plugin';
1211
export { createAngularSetupMiddlewaresPlugin, ServerSsrMode } from './setup-middlewares-plugin';
1312
export { createAngularSsrTransformPlugin } from './ssr-transform-plugin';

0 commit comments

Comments
 (0)