From 01b2fcbdb99e37614181e3cc7191c8dfe9f756e8 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Tue, 3 Mar 2026 00:31:21 +0800 Subject: [PATCH 1/3] test: reproduce getPrerenderPaths limitation with virtual modules The configFile: false fix (#12) prevents user plugins from loading during collectPrerenderPaths, so getPrerenderPaths that imports a virtual module silently fails to resolve prerender paths. Co-Authored-By: Claude Opus 4.6 --- .../static-pages/pages/tags/[tag].server.ts | 16 +++++++++++++++ playground/static-pages/pages/tags/[tag].vue | 9 +++++++++ playground/static-pages/vite.config.ts | 20 +++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 playground/static-pages/pages/tags/[tag].server.ts create mode 100644 playground/static-pages/pages/tags/[tag].vue diff --git a/playground/static-pages/pages/tags/[tag].server.ts b/playground/static-pages/pages/tags/[tag].server.ts new file mode 100644 index 000000000..dc61013be --- /dev/null +++ b/playground/static-pages/pages/tags/[tag].server.ts @@ -0,0 +1,16 @@ +import { defineHandler } from "void"; +import { tags } from "virtual:tags"; + +export interface Props { + tag: string; +} + +export const prerender = true; + +export function getPrerenderPaths() { + return tags.map((tag: string) => ({ tag })); +} + +export const loader = defineHandler((c) => { + return { tag: c.req.param("tag") }; +}); diff --git a/playground/static-pages/pages/tags/[tag].vue b/playground/static-pages/pages/tags/[tag].vue new file mode 100644 index 000000000..d96eee207 --- /dev/null +++ b/playground/static-pages/pages/tags/[tag].vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/static-pages/vite.config.ts b/playground/static-pages/vite.config.ts index 44c74f311..02abc9b1c 100644 --- a/playground/static-pages/vite.config.ts +++ b/playground/static-pages/vite.config.ts @@ -1,7 +1,23 @@ -import { defineConfig } from "vite"; +import { defineConfig, type Plugin } from "vite"; import { voidPlugin } from "void"; import { voidVue } from "@void-x/vue"; +function virtualTagsPlugin(): Plugin { + const VIRTUAL_ID = "virtual:tags"; + const RESOLVED_ID = "\0virtual:tags"; + return { + name: "virtual-tags", + resolveId(id) { + if (id === VIRTUAL_ID) return RESOLVED_ID; + }, + load(id) { + if (id === RESOLVED_ID) { + return `export const tags = ["vue", "vite"];`; + } + }, + }; +} + export default defineConfig({ - plugins: [voidPlugin(), voidVue()], + plugins: [voidPlugin(), voidVue(), virtualTagsPlugin()], }); From 070ed2bfbe563e92405b75899bf412ba09de2c10 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Tue, 3 Mar 2026 09:31:15 +0800 Subject: [PATCH 2/3] test: assert virtual module prerender paths should be generated This will fail until collectPrerenderPaths loads user plugins. Co-Authored-By: Claude Opus 4.6 --- packages/void/test/integration/static-pages.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/void/test/integration/static-pages.test.ts b/packages/void/test/integration/static-pages.test.ts index c37e2e35d..b83ba5f59 100644 --- a/packages/void/test/integration/static-pages.test.ts +++ b/packages/void/test/integration/static-pages.test.ts @@ -73,6 +73,18 @@ describe("playground/static-pages build (output: static)", () => { expect(html).toContain("Post hello"); }); + it("prerenders dynamic pages with getPrerenderPaths using virtual modules", () => { + // tags/[tag] exports getPrerenderPaths that imports from virtual:tags plugin + const vuePath = join(DIST, "client/tags/vue.html"); + const vitePath = join(DIST, "client/tags/vite.html"); + expect(existsSync(vuePath)).toBe(true); + expect(existsSync(vitePath)).toBe(true); + + const html = readFileSync(vuePath, "utf-8"); + expect(html).toContain('data-testid="tag-title"'); + expect(html).toContain("Tag vue"); + }); + it("does not prerender dynamic pages without getPrerenderPaths", () => { // items/[id] has no getPrerenderPaths, so it should NOT be prerendered expect(existsSync(join(DIST, "client/items"))).toBe(false); From 13d380f520fb550aee8a6b4297eaa380402b75f0 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Tue, 3 Mar 2026 09:53:18 +0800 Subject: [PATCH 3/3] fix: error on failed getPrerenderPaths instead of silent warning If a user explicitly exports getPrerenderPaths and it fails to resolve, the build should fail with a clear error instead of silently skipping the page. Co-Authored-By: Claude Opus 4.6 --- packages/void/src/prerender-paths.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/void/src/prerender-paths.ts b/packages/void/src/prerender-paths.ts index 0d0715d15..587fc765e 100644 --- a/packages/void/src/prerender-paths.ts +++ b/packages/void/src/prerender-paths.ts @@ -65,8 +65,8 @@ export async function collectPrerenderPaths(options: { } } } catch (err) { - console.warn( - `[void] Failed to resolve prerender paths for ${page.pattern}: ${err instanceof Error ? err.message : String(err)}`, + throw new Error( + `Failed to resolve prerender paths for ${page.pattern}: ${err instanceof Error ? err.message : String(err)}`, ); } } @@ -97,8 +97,8 @@ export async function collectPrerenderPaths(options: { } } } catch (err) { - console.warn( - `[void] Failed to resolve SSR prerender paths: ${err instanceof Error ? err.message : String(err)}`, + throw new Error( + `Failed to resolve SSR prerender paths: ${err instanceof Error ? err.message : String(err)}`, ); } finally { await viteServer.close();