Repository navigation
Conversation
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 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds a tags/[tag] dynamic page to the static-pages playground to demonstrate a known framework limitation: because collectPrerenderPaths uses createServer({ configFile: false }) (the fix from issue #12), user plugins (such as virtual module plugins or resolve.alias entries) are not loaded when getPrerenderPaths runs. The result is that tags/vue.html and tags/vite.html are never generated, with a silent warning about Cannot find module 'virtual:tags'.
Changes:
- Introduces a
virtualTagsPlugin()invite.config.tsthat serves avirtual:tagsmodule exporting["vue", "vite"] - Adds
pages/tags/[tag].vue— the Vue component for the tag page - Adds
pages/tags/[tag].server.ts— importsvirtual:tagsingetPrerenderPathsto trigger the limitation
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
playground/static-pages/vite.config.ts |
Adds a virtualTagsPlugin Vite plugin providing the virtual:tags virtual module |
playground/static-pages/pages/tags/[tag].vue |
New Vue component rendering a tag page with a data-testid attribute |
playground/static-pages/pages/tags/[tag].server.ts |
New server file importing virtual:tags in getPrerenderPaths, reproducing the silent failure |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function getPrerenderPaths() { | ||
| return tags.map((tag: string) => ({ tag })); |
There was a problem hiding this comment.
The PR's stated purpose is to reproduce a known limitation — virtual module imports (and resolve.alias) silently fail during getPrerenderPaths because collectPrerenderPaths uses createServer({ configFile: false }). However, the existing static-pages.test.ts integration test is not updated to document or assert on this behavior.
Without a corresponding test case asserting that tags/vue.html and tags/vite.html are not generated (e.g., expect(existsSync(join(DIST, "client/tags/vue.html"))).toBe(false)), there is no automated check capturing the limitation. This means the limitation could be silently "fixed" or "broken" without any test reflecting the change.
Consider adding a test case to packages/void/test/integration/static-pages.test.ts that explicitly documents this known limitation — for example, asserting that the tag pages are absent from the build output due to the virtual module resolution failure. Such a test would also serve as a regression test once the limitation is eventually fixed (the test expectation would be inverted).
This will fail until collectPrerenderPaths loads user plugins. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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 <noreply@anthropic.com>
…pport `collectPrerenderPaths()` creates a temporary Vite dev server to call `ssrLoadModule()` on page files that export `getPrerenderPaths`. Previously it used `configFile: false`, which meant no user plugins were loaded — any `getPrerenderPaths` that imported from a virtual module or relied on resolve aliases would silently fail. Now uses `loadConfigFromFile()` to fully load the user's Vite config, then filters out only the two problematic plugin sets: - `void:*` plugins — would cause recursion (prerenderPlugin → collectPrerenderPaths → createServer → voidPlugin → prerenderPlugin...) - `vite-plugin-cloudflare*` — replaces SSR environment with FetchableDevEnvironment that requires a running Miniflare backend, making ssrLoadModule() unusable All other user plugins (virtual modules, resolve aliases, etc.) are forwarded to the temporary server, ensuring consistent module resolution. Fixes #12, supersedes #13. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Superseded by #16 — virtual module tests and error handling consolidated there. |
…transform Vite's SSR dep optimizer prebundled @void/solid with esbuild's default automatic JSX transform, emitting imports of react/jsx-runtime that failed to resolve. Set optimizeDeps.exclude, ssr.noExternal, and ssr.optimizeDeps.exclude from voidSolid() so vite-plugin-solid sees the .tsx source directly. Closes #13
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Summary
tags/[tag]page to thestatic-pagesplayground that imports from avirtual:tagsplugin module ingetPrerenderPathsconfigFile: false(fix for bug: SSG prerender crashes on dynamic pages with getPrerenderPaths (FetchableDevEnvironment missing hot.api) #12) prevents user plugins from loading duringcollectPrerenderPaths, so virtual module imports silently failtags/vue.htmlandtags/vite.htmlshould be prerenderedThe fundamental problem
The
configFile: falsefix avoids theFetchableDevEnvironmentcrash by not loading the user's config at all. But this means thessrLoadModuleruntime used bycollectPrerenderPathsis inconsistent with the user's actual Vite environment — no user plugins, noresolve.alias, no customresolveconfig.The most severe case is plugins providing virtual modules (reproduced here) — any
getPrerenderPathsthat imports from a virtual module will silently fail. Smaller cases include customresolve.alias(e.g.{ "@": "./src" }) and otherresolveconfig that users may rely on in their server files.Why CI fails
The test failure is intentional — it's caused by the assertion we added in this PR, not by a regression. Before #14,
collectPrerenderPathssilently swallowed the error as aconsole.warnand the build succeeded (just with missing pages). After #14 lands, the build itself will fail with a hard error instead.Related
configFile: falsegetPrerenderPathsinstead of silent warning #14 — changes the silent warning into a hard build error🤖 Generated with Claude Code