diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts index ef33e9e5ec0c..c1ee820d6f1b 100644 --- a/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts @@ -142,7 +142,7 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expect(await response?.headers.get('Location')).toBe('/login/'); }); - it('serves a JavaScript asset named as a bundle', async () => { + it('serves a JavaScript asset named as a bundle (main.js)', async () => { await harness.writeFile('public/test/main.js', javascriptFileContent); setupTarget(harness, { @@ -162,5 +162,17 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expect(result?.success).toBeTrue(); expect(await response?.text()).toContain(javascriptFileContent); }); + + it('should return 404 when a JavaScript asset named as a bundle (main.js) does not exist', async () => { + setupTarget(harness, {}); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'unknown/main.js'); + expect(result?.success).toBeTrue(); + expect(response?.status).toBe(404); + }); }); }); 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 fb4062625f47..e76573c30151 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -808,7 +808,11 @@ export async function setupServer( }, // This is needed when `externalDependencies` is used to prevent Vite load errors. // NOTE: If Vite adds direct support for externals, this can be removed. - preTransformRequests: externalMetadata.explicitBrowser.length === 0, + // NOTE: Vite breaks the resolution of browser modules in SSR + // when accessing a url with two or more segments (e.g., 'foo/bar'), + // as they are not re-based from the base href. + preTransformRequests: + externalMetadata.explicitBrowser.length === 0 && ssrMode === ServerSsrMode.NoSsr, }, ssr: { // Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored. diff --git a/packages/angular/build/src/tools/vite/plugins/angular-memory-plugin.ts b/packages/angular/build/src/tools/vite/plugins/angular-memory-plugin.ts index b585e05aa7e0..f8a4c004ec0e 100644 --- a/packages/angular/build/src/tools/vite/plugins/angular-memory-plugin.ts +++ b/packages/angular/build/src/tools/vite/plugins/angular-memory-plugin.ts @@ -62,24 +62,12 @@ export async function createAngularMemoryPlugin( return source; } - if (importer) { + if (importer && source[0] === '.') { const normalizedImporter = normalizePath(importer); - if (source[0] === '.' && normalizedImporter.startsWith(virtualProjectRoot)) { + if (normalizedImporter.startsWith(virtualProjectRoot)) { // Remove query if present const [importerFile] = normalizedImporter.split('?', 1); source = '/' + join(dirname(relative(virtualProjectRoot, importerFile)), source); - } else if ( - !ssr && - source[0] === '/' && - importer.endsWith('index.html') && - normalizedImporter.startsWith(virtualProjectRoot) - ) { - // This is only needed when using SSR and `angularSsrMiddleware` (old style) to correctly resolve - // .js files when using lazy-loading. - // Remove query if present - const [importerFile] = normalizedImporter.split('?', 1); - source = - '/' + join(dirname(relative(virtualProjectRoot, importerFile)), basename(source)); } }