fix: thread Vite base through SSR manifest and Nitro baseURL#2152
fix: thread Vite base through SSR manifest and Nitro baseURL#2152bigmistqke wants to merge 4 commits into
base through SSR manifest and Nitro baseURL#2152Conversation
Asserts getSsrProdManifest().path() / .getAssets() / .json() emit URLs prefixed with import.meta.env.BASE_URL. Currently red: every emitted path is rooted at '/', so subpath-deployed apps load script and CSS tags from the wrong origin path.
The prod SSR manifest hard-coded '/' as the prefix for entry script src,
modulepreload/stylesheet hrefs, and the serialized window.manifest output
paths. Under a deploy base ('/repo/' on GitHub Pages, etc.) every emitted
URL pointed at the wrong origin path, so the prerendered HTML loaded
nothing and the app failed to hydrate.
Replace '/' with import.meta.env.BASE_URL via pathe.join, matching the
dev-ssr-manifest's existing base-aware joins. Apply the same fix to the
dev-client-manifest's dynamic import.
Today the plugin defaults Nitro's baseURL to '/' regardless of the
project's Vite base. On a subpath deploy ('base: "/repo/"' for GitHub
Pages, etc.) Nitro then prerenders, route-prefixes, and serves at the
wrong path, forcing users to pass the prefix to both Vite and the plugin.
Capture the resolved Vite base in configResolved and use it as the
nitroConfig.baseURL default. A user-supplied nitroV2Plugin({ baseURL }) is
still honored because the spread comes after the default.
|
✅ Deploy Preview for solid-start-landing-page ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
commit: |
|
Is this only necessary for nitro v2? what is the behavior for v3 |
|
The Nitro v2 vite plugin is now deprecated. If you experience this on Nitro v3 with SolidStart v2 as well, feel free to open a new ticket |
Hey all 👋
I wanted to deploy
solidbaseto gh-pages, but I needed to add basePath awareness toSolidStartso I vibecoded it withclaude.[after this line all is written by claude]
Fixes #2151.
Summary
Under a non-root Vite
base, the prod SSR manifest emits root-absolute URLs for scripts, modulepreload, and stylesheets, and@solidjs/vite-plugin-nitro-2ignores the same base for Nitro routing. Subpath deploys (GitHub Pages, reverse-proxied paths, embedded mounts) ship HTML that 404s every asset.This restores the v1 behavior — base flows through the build manifest — without changing any public API or adding a new helper.
Changes
prod-ssr-manifest.ts— replacejoin("/", ...)withjoin(import.meta.env.BASE_URL, ...)inpath,getAssets, andjson. Matches the existing pattern indev-ssr-manifest.ts.dev-client-manifest.ts— same fix for the dev-mode dynamic import.vite-plugin-nitro-2— capture Vite's resolvedconfig.baseinconfigResolvedand use it as thenitroConfig.baseURLdefault. A user-suppliednitroV2Plugin({ baseURL })still wins because the spread comes after.pathe.joincollapses correctly whenBASE_URL === "/", so the no-base case is unchanged (verified with a smoke build ofapps/tests).Tests
New
packages/start/src/server/manifest/prod-ssr-manifest.spec.tscovers:path(id)returns BASE_URL-prefixed paths.getAssets(id)hrefs all sit under BASE_URL.json()output paths are BASE_URL-prefixed."/"still emits single-slash URLs.6/6 pass after the fix.
Manual verification
apps/testsbuilt twice — once withbase: "/sub/", once default. With base, every script/link tag is correctly prefixed and the Nitro server listens at/sub. Without base, output is byte-identical to main.What this PR does NOT cover
This fixes framework-emitted URLs. User-authored root-absolute paths still need to be base-aware on the user's side — the framework can't safely rewrite arbitrary string literals in user code. Specifically:
entry-server.tsxstatic<head>references —<link rel="icon" href="/favicon.ico" />,<link rel="manifest" href="/site.webmanifest" />,<meta property="og:image" content="/og.png" />, etc. These live in user JSX, not the build manifest, so they ship as-is. Authors should use${import.meta.env.BASE_URL}favicon.ico(or a small helper).<a href="/...">— Solid Router's<A>prepends base; plain<a>does not unless the click is intercepted. Recommend<A>for in-app navigation.url(/foo)and<img src="/foo">— same story. Vite handles asset imports (import logo from "./logo.png") andnew URL("./asset", import.meta.url)correctly; raw string paths are the user's responsibility.siteUrlconfig, not Vitebase.A follow-up could ship a tiny
withBase(path)helper from@solidjs/startto make the user-side calls less noisy, but that's a separate discussion.Out of scope (also follow-up)
baseto<Router>inapp.tsx. Touches the router integration; happy to follow up if maintainers want it.<Router base>semantics in@solidjs/router.Commits
0147d17test(start): fail when prod SSR manifest ignores deploy basee872ac8fix(start): thread BASE_URL through SSR manifest paths4bb7d84fix(vite-plugin-nitro-2): inherit Vite config.base as the Nitro baseURL