From a5db8d2ad02275e6cc989bd0a04ff2845f6f34c4 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Sat, 16 Dec 2023 01:19:43 +0800 Subject: [PATCH] Simplify vue appEntrypoint handling (#9362) * Simplify vue appEntrypoint handling * Try fix windows --------- Co-authored-by: Nate Moore --- .changeset/rotten-olives-beg.md | 5 ++ packages/integrations/vue/src/index.ts | 100 ++++++++++--------------- 2 files changed, 43 insertions(+), 62 deletions(-) create mode 100644 .changeset/rotten-olives-beg.md diff --git a/.changeset/rotten-olives-beg.md b/.changeset/rotten-olives-beg.md new file mode 100644 index 000000000000..0ee34221dae8 --- /dev/null +++ b/.changeset/rotten-olives-beg.md @@ -0,0 +1,5 @@ +--- +'@astrojs/vue': patch +--- + +Simplifies `appEntrypoint` handling diff --git a/packages/integrations/vue/src/index.ts b/packages/integrations/vue/src/index.ts index ef35055877d7..74da239350f2 100644 --- a/packages/integrations/vue/src/index.ts +++ b/packages/integrations/vue/src/index.ts @@ -1,21 +1,15 @@ +import path from 'node:path'; import type { Options as VueOptions } from '@vitejs/plugin-vue'; -import type { Options as VueJsxOptions } from '@vitejs/plugin-vue-jsx'; -import type { AstroIntegration, AstroIntegrationLogger, AstroRenderer } from 'astro'; -import type { UserConfig, Plugin } from 'vite'; - -import { fileURLToPath } from 'node:url'; import vue from '@vitejs/plugin-vue'; +import type { Options as VueJsxOptions } from '@vitejs/plugin-vue-jsx'; +import type { AstroIntegration, AstroRenderer } from 'astro'; +import type { Plugin, UserConfig } from 'vite'; interface Options extends VueOptions { jsx?: boolean | VueJsxOptions; appEntrypoint?: string; } -interface ViteOptions extends Options { - root: URL; - logger: AstroIntegrationLogger; -} - function getRenderer(): AstroRenderer { return { name: '@astrojs/vue', @@ -39,71 +33,55 @@ function getJsxRenderer(): AstroRenderer { }; } -function virtualAppEntrypoint(options: ViteOptions) { +function virtualAppEntrypoint(options?: Options): Plugin { const virtualModuleId = 'virtual:@astrojs/vue/app'; const resolvedVirtualModuleId = '\0' + virtualModuleId; - let getExports: (id: string) => Promise; + + let isBuild: boolean; + let root: string; + return { name: '@astrojs/vue/virtual-app', - buildStart() { - if (!getExports) { - getExports = async (id: string) => { - const info = await this.load.call(this, { id }); - return info.exports ?? []; - }; - } + config(_, { command }) { + isBuild = command === 'build'; }, - configureServer(server) { - if (!getExports) { - getExports = async (id: string) => { - const mod = await server.ssrLoadModule(id); - return Object.keys(mod) ?? []; - }; - } + configResolved(config) { + root = config.root; }, resolveId(id: string) { if (id == virtualModuleId) { return resolvedVirtualModuleId; } }, - async load(id: string) { - const noop = `export const setup = (app) => app;`; + load(id: string) { if (id === resolvedVirtualModuleId) { - if (options.appEntrypoint) { - try { - let resolved; - if (options.appEntrypoint.startsWith('.')) { - resolved = await this.resolve( - fileURLToPath(new URL(options.appEntrypoint, options.root)) - ); - } else { - resolved = await this.resolve(options.appEntrypoint, fileURLToPath(options.root)); - } - if (!resolved) { - // This error is handled below, the message isn't shown to the user - throw new Error('Unable to resolve appEntrypoint'); - } - const exports = await getExports(resolved.id); - if (!exports.includes('default')) { - options.logger.warn( - `appEntrypoint \`${options.appEntrypoint}\` does not export a default function. Check out https://docs.astro.build/en/guides/integrations-guide/vue/#appentrypoint.` - ); - return noop; - } - return `export { default as setup } from "${resolved.id}";`; - } catch { - options.logger.warn( - `Unable to resolve appEntrypoint \`${options.appEntrypoint}\`. Does the file exist?` - ); - } + if (options?.appEntrypoint) { + const appEntrypoint = options.appEntrypoint.startsWith('.') + ? path.resolve(root, options.appEntrypoint) + : options.appEntrypoint; + + return `\ +import * as mod from ${JSON.stringify(appEntrypoint)}; + +export const setup = (app) => { + if ('default' in mod) { + mod.default(app); + } else { + ${ + !isBuild + ? `console.warn("[@astrojs/vue] appEntrypoint \`" + ${JSON.stringify(appEntrypoint)} + "\` does not export a default function. Check out https://docs.astro.build/en/guides/integrations-guide/vue/#appentrypoint.");` + : '' + } + } +}`; } - return noop; + return `export const setup = () => {};`; } }, - } satisfies Plugin; + }; } -async function getViteConfiguration(options: ViteOptions): Promise { +async function getViteConfiguration(options?: Options): Promise { const config: UserConfig = { optimizeDeps: { include: ['@astrojs/vue/client.js', 'vue'], @@ -129,14 +107,12 @@ export default function (options?: Options): AstroIntegration { return { name: '@astrojs/vue', hooks: { - 'astro:config:setup': async ({ addRenderer, updateConfig, config, logger }) => { + 'astro:config:setup': async ({ addRenderer, updateConfig }) => { addRenderer(getRenderer()); if (options?.jsx) { addRenderer(getJsxRenderer()); } - updateConfig({ - vite: await getViteConfiguration({ ...options, root: config.root, logger }), - }); + updateConfig({ vite: await getViteConfiguration(options) }); }, }, };