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 39b27b2bd6c7..64c68fd26888 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -803,6 +803,26 @@ function getDepOptimizationConfig({ thirdPartySourcemaps: boolean; }): DepOptimizationConfig { const plugins: ViteEsBuildPlugin[] = [ + { + name: 'angular-browser-node-built-in', + setup(build) { + // This namespace is configured by vite. + // @see: https://github.com/vitejs/vite/blob/a1dd396da856401a12c921d0cd2c4e97cb63f1b5/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L109 + build.onLoad({ filter: /.*/, namespace: 'browser-external' }, (args) => { + if (!isBuiltin(args.path)) { + return; + } + + return { + errors: [ + { + text: `The package "${args.path}" wasn't found on the file system but is built into node.`, + }, + ], + }; + }); + }, + }, { name: `angular-vite-optimize-deps${ssr ? '-ssr' : ''}${ thirdPartySourcemaps ? '-vendor-sourcemap' : '' diff --git a/tests/legacy-cli/e2e/tests/vite/browser-node-module-dep-error.ts b/tests/legacy-cli/e2e/tests/vite/browser-node-module-dep-error.ts new file mode 100644 index 000000000000..13a384a1b792 --- /dev/null +++ b/tests/legacy-cli/e2e/tests/vite/browser-node-module-dep-error.ts @@ -0,0 +1,21 @@ +import assert from 'node:assert'; +import { execAndWaitForOutputToMatch, ng } from '../../utils/process'; +import { writeFile } from '../../utils/fs'; + +export default async function () { + await ng('cache', 'clean'); + await ng('cache', 'on'); + + // The `@angular/cli` package relies on Node.js dependencies and is not designed for use in a browser environment. + await writeFile('src/main.ts', `import '@angular/cli';`); + + const { stderr } = await execAndWaitForOutputToMatch('ng', ['serve', '--port=0'], /ERROR/, { + CI: '0', + NO_COLOR: 'true', + }); + + assert.match( + stderr, + /The package "node:util" wasn't found on the file system but is built into node/, + ); +}