From 37a2138cb474778ef398a8d4129e1c389dde0f44 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Thu, 18 Jul 2024 17:59:54 -0400 Subject: [PATCH] fix(@angular/build): account for HTML base HREF for dev-server externals When adjusting URLs to support explicit external dependencies when using Vite, the workaround will now account for the presence of a base HREF value within the specifier. Vite will automatically add the base HREF as a prefix to the path when specified. This previously resulted in invalid specifiers due to the partial removal of the Vite specific `@id` path prefix. --- .../build-external-dependencies_spec.ts | 38 +++++++++++++++++++ .../build/src/tools/vite/id-prefix-plugin.ts | 4 +- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/build-external-dependencies_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/build-external-dependencies_spec.ts index 42405a75181e..583f988ba12a 100644 --- a/packages/angular/build/src/builders/dev-server/tests/behavior/build-external-dependencies_spec.ts +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/build-external-dependencies_spec.ts @@ -45,5 +45,43 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expect(text).toContain(`import { BehaviorSubject } from "rxjs";`); expect(text).toContain(`import { map } from "rxjs/operators";`); }); + + it('respects import specifiers when using baseHref with trailing slash', async () => { + setupTarget(harness, { + externalDependencies: ['rxjs', 'rxjs/operators'], + baseHref: '/test/', + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'main.js'); + + expect(result?.success).toBeTrue(); + + const text = await response?.text(); + expect(text).toContain(`import { BehaviorSubject } from "rxjs";`); + expect(text).toContain(`import { map } from "rxjs/operators";`); + }); + + it('respects import specifiers when using baseHref without trailing slash', async () => { + setupTarget(harness, { + externalDependencies: ['rxjs', 'rxjs/operators'], + baseHref: '/test', + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'main.js'); + + expect(result?.success).toBeTrue(); + + const text = await response?.text(); + expect(text).toContain(`import { BehaviorSubject } from "rxjs";`); + expect(text).toContain(`import { map } from "rxjs/operators";`); + }); }); }); diff --git a/packages/angular/build/src/tools/vite/id-prefix-plugin.ts b/packages/angular/build/src/tools/vite/id-prefix-plugin.ts index b1a8e8782979..e4e4620baa1e 100644 --- a/packages/angular/build/src/tools/vite/id-prefix-plugin.ts +++ b/packages/angular/build/src/tools/vite/id-prefix-plugin.ts @@ -11,7 +11,7 @@ import type { Plugin } from 'vite'; // NOTE: the implementation for this Vite plugin is roughly based on: // https://github.com/MilanKovacic/vite-plugin-externalize-dependencies -const VITE_ID_PREFIX = '/@id/'; +const VITE_ID_PREFIX = '@id/'; const escapeRegexSpecialChars = (inputString: string): string => { return inputString.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string @@ -29,7 +29,7 @@ export function createRemoveIdPrefixPlugin(externals: string[]): Plugin { const escapedExternals = externals.map(escapeRegexSpecialChars); const prefixedExternalRegex = new RegExp( - `${VITE_ID_PREFIX}(${escapedExternals.join('|')})`, + `${resolvedConfig.base}${VITE_ID_PREFIX}(${escapedExternals.join('|')})`, 'g', );