From f9d48c2d322c567d441bc0c3760c35987a1f19b6 Mon Sep 17 00:00:00 2001 From: Maruthan G Date: Mon, 6 Apr 2026 17:17:58 +0530 Subject: [PATCH] fix(@angular/build): allow serving node_modules assets in monorepo setups In monorepo setups where node_modules are hoisted to a parent directory above the Angular workspace root, assets loaded from those packages (e.g., fonts from CSS files) were blocked by Vite's dev server with a 403 error. This was caused by the explicit `server.fs.allow` configuration only including the workspace root's `node_modules`, which overrides Vite's default package root detection. By adding `searchForPackageRoot()` to the allow list, the monorepo root directory is included, allowing access to hoisted node_modules. Fixes #31016 --- .../angular/build/src/builders/dev-server/vite/server.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 73f58ad5c348..bc339bf3c33e 100644 --- a/packages/angular/build/src/builders/dev-server/vite/server.ts +++ b/packages/angular/build/src/builders/dev-server/vite/server.ts @@ -8,7 +8,7 @@ import { readFile } from 'node:fs/promises'; import { join } from 'node:path'; -import type { Connect, InlineConfig, SSROptions, ServerOptions } from 'vite'; +import { type Connect, type InlineConfig, type SSROptions, type ServerOptions, searchForPackageRoot } from 'vite'; import type { ComponentStyleRecord } from '../../../tools/vite/middlewares'; import { ServerSsrMode, @@ -75,9 +75,12 @@ async function createServerConfig( // The first two are required for Vite to function in prebundling mode (the default) and to load // the Vite client-side code for browser reloading. These would be available by default but when // the `allow` option is explicitly configured, they must be included manually. + // The package root search handles monorepo setups where node_modules may be hoisted + // to a parent directory above the Angular workspace root. allow: [ cacheDir, join(serverOptions.workspaceRoot, 'node_modules'), + searchForPackageRoot(serverOptions.workspaceRoot), ...[...assets.values()].map(({ source }) => source), ], },