diff --git a/.changeset/ninety-garlics-fly.md b/.changeset/ninety-garlics-fly.md new file mode 100644 index 000000000000..03ee22f2d367 --- /dev/null +++ b/.changeset/ninety-garlics-fly.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix importing client-side components with alias diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 561b24372473..03084625b9af 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -22,6 +22,7 @@ import { generatePages } from './generate.js'; import { trackPageData } from './internal.js'; import type { PageBuildData, StaticBuildOptions } from './types'; import { getTimeStat } from './util.js'; +import { vitePluginAliasResolve } from './vite-plugin-alias-resolve.js'; import { vitePluginAnalyzer } from './vite-plugin-analyzer.js'; import { rollupPluginAstroBuildCSS } from './vite-plugin-css.js'; import { vitePluginHoistedScripts } from './vite-plugin-hoisted-scripts.js'; @@ -221,6 +222,7 @@ async function clientBuild( }, }, plugins: [ + vitePluginAliasResolve(internals), vitePluginInternals(input, internals), vitePluginHoistedScripts(settings, internals), rollupPluginAstroBuildCSS({ diff --git a/packages/astro/src/core/build/vite-plugin-alias-resolve.ts b/packages/astro/src/core/build/vite-plugin-alias-resolve.ts new file mode 100644 index 000000000000..ac37e66cd6fb --- /dev/null +++ b/packages/astro/src/core/build/vite-plugin-alias-resolve.ts @@ -0,0 +1,50 @@ +import type { Alias, Plugin as VitePlugin } from 'vite'; +import type { BuildInternals } from '../../core/build/internal.js'; + +/** + * `@rollup/plugin-alias` doesn't resolve aliases in Rollup input by default. This plugin fixes it + * with a partial fork of it's resolve function. https://github.com/rollup/plugins/blob/master/packages/alias/src/index.ts + * When https://github.com/rollup/plugins/pull/1402 is merged, we can remove this plugin. + */ +export function vitePluginAliasResolve(internals: BuildInternals): VitePlugin { + let aliases: Alias[]; + + return { + name: '@astro/plugin-alias-resolve', + enforce: 'pre', + configResolved(config) { + aliases = config.resolve.alias; + }, + async resolveId(id, importer, opts) { + if ( + !importer && + (internals.discoveredHydratedComponents.has(id) || + internals.discoveredClientOnlyComponents.has(id)) + ) { + const matchedEntry = aliases.find((entry) => matches(entry.find, id)); + if (!matchedEntry) { + return null; + } + + const updatedId = id.replace(matchedEntry.find, matchedEntry.replacement); + + return this.resolve(updatedId, importer, Object.assign({ skipSelf: true }, opts)).then( + (resolved) => resolved || { id: updatedId } + ); + } + }, + }; +} + +function matches(pattern: string | RegExp, importee: string) { + if (pattern instanceof RegExp) { + return pattern.test(importee); + } + if (importee.length < pattern.length) { + return false; + } + if (importee === pattern) { + return true; + } + return importee.startsWith(pattern + '/'); +} diff --git a/packages/astro/test/alias.test.js b/packages/astro/test/alias.test.js index 82b05413a4b3..20a213111593 100644 --- a/packages/astro/test/alias.test.js +++ b/packages/astro/test/alias.test.js @@ -35,4 +35,21 @@ describe('Aliases', () => { expect(scripts.length).to.be.greaterThan(0); }); }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('can load client components', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + + // Should render aliased element + expect($('#client').text()).to.equal('test'); + + const scripts = $('script').toArray(); + expect(scripts.length).to.be.greaterThan(0); + }); + }); });