Skip to content

[nitro 1/6] Serve the client through Nitro's Vite plugin - #4701

Draft
cprecioso wants to merge 2 commits into
mainfrom
cprecioso/nitro-01-client
Draft

[nitro 1/6] Serve the client through Nitro's Vite plugin#4701
cprecioso wants to merge 2 commits into
mainfrom
cprecioso/nitro-01-client

Conversation

@cprecioso

Copy link
Copy Markdown
Member

Description

Part 1 of the Nitro migration stack (plan + spike findings in the workspace .context/; spikes validated everything on nitro@3.0.260610-beta + Vite 8.2.0).

Nitro now serves the client (dev + build + prerender), replacing @wasp.sh/lib-vite-ssr. The Express server is untouched and still runs standalone on 3001 — this PR changes nothing about how operations/auth/APIs are served.

What changes:

  • wasp() composes a new waspNitroBridge() plugin + nitro() from nitro/vite instead of ssr() from @wasp.sh/lib-vite-ssr. The bridge sets the client/ssr environment inputs and injects the Nitro config (custom renderer, prerender.routes from prerender: true declarations, node-server preset, serverEntry: false).
  • Renderer follows Nitro's blessed two-file architecture: a plain-TS thin proxy (fetchViteEnv("ssr", req)) as renderer.handler (the prerender pass rebuilds this file with bare Rolldown, so it cannot contain JSX/CSS/?assets), plus the reworked ssr-environment entry that fully renders prerender-listed routes and serves a memoized SPA shell for everything else.
  • Asset tags come from Nitro's ?assets imports; layout.tsx renders them as head children instead of the manual clientEntrySrc script, and the react-refresh preamble moves into the client entry (removes the Dev-mode: async client-entry races React-Refresh preamble → intermittent "can't detect preamble" / failed hydration (0.22, still on 0.23) #4258-adjacent script-injection workaround).
  • detectServerImports / validateEnv / typescriptCheck are scoped per Vite environment (there are three now: client, ssr, nitro).
  • Nitro output lands at .wasp/out/web-app with publicDir = web-app/build, so viteBuildDirPath consumers (deploy package, wasp build start) keep working unchanged. 200.html is kept (Fly/Railway static deploys hardcode it) as a prerender route.
  • waspConfig pins the dev port against PORT in user .env files (Nitro pre-loads .env and gives process.env.PORT top precedence).

Verified: 657/657 unit tests; e2e goldens regenerated and re-verified in comparison mode (937/937 twice); on a live app — dev with working Fast Refresh and clean hydration, prerendered route HTML with hydration data, SPA-shell fallback, operations roundtrip to the 3001 server in dev and preview, and all env/TS/server-import guards still firing.

Notes for review:

  • nitroVersion is a plain String in DepVersions.hs — Wasp's SemVer parser doesn't support pre-release identifiers (-beta).
  • Nitro output config is injected only on command === "build" — setting it in dev makes Nitro serve stale build files through its production asset reader (500s). Upstream issue drafted.
  • Changelog/docs/migration-guide entries are deferred to the final stack PR (the stack lands behind a release freeze).

Type of change

  • 🔧 Just code/docs improvement
  • 🐞 Bug fix
  • 🚀 New/improved feature
  • 💥 Breaking change

Checklist

  • I tested my change in a Wasp app to verify that it works as intended.

  • 🧪 Tests and apps:

    • I added unit tests for my change.
    • (if you fixed a bug) I added a regression test for the bug I fixed.
    • (if you added/updated a feature) I added/updated e2e tests in examples/kitchen-sink/e2e-tests.
    • (if you added/updated a feature) I updated the starter templates in waspc/data/Cli/templates, as needed.
    • (if you added/updated a feature) I updated the example apps in examples/, as needed.
      • (if you updated examples/tutorials) I updated the tutorial in the docs (and vice versa).
  • 📜 Documentation:

    • (if you added/updated a feature) I added/updated the documentation in web/docs/.
  • 🆕 Changelog: (if change is more than just code/docs improvement)

    • I updated waspc/ChangeLog.md with a user-friendly description of the change.
    • (if you did a breaking change) I added a step to the current migration guide in web/docs/migration-guides/.
    • I bumped the version in waspc/waspc.cabal to reflect the changes I introduced.

Replace @wasp.sh/lib-vite-ssr with nitro/vite in the SDK Vite plugin chain:
- new waspNitroBridge() plugin injects client/ssr environment inputs and
  the Nitro config (custom renderer, prerender routes, node-server preset)
- renderer split per Nitro's architecture: plain-TS thin proxy
  (fetchViteEnv) + ssr-environment entry with ?assets tag collection
- layout.tsx takes asset tags as head children instead of clientEntrySrc;
  react-refresh preamble moves into the client entry
- detectServerImports/validateEnv/typescriptCheck scoped per environment
- waspConfig pins the dev port against .env PORT hijacking and drops the
  forced client outDir (Nitro owns output at .wasp/out/web-app)
- nitro pinned exactly (3.0.260610-beta); lib-vite-ssr no longer shipped

The Express server is untouched and still serves on 3001; prerender
(prerender: true routes) and the SPA-shell fallback now go through
Nitro's renderer in both dev and build.
@pkg-pr-new

pkg-pr-new Bot commented Aug 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

@wasp.sh/spec

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/spec@4701

@wasp.sh/wasp-cli

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli@4701

@wasp.sh/wasp-cli-darwin-arm64-unknown

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli-darwin-arm64-unknown@4701

@wasp.sh/wasp-cli-darwin-x64-unknown

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli-darwin-x64-unknown@4701

@wasp.sh/wasp-cli-linux-arm64-glibc

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli-linux-arm64-glibc@4701

@wasp.sh/wasp-cli-linux-x64-glibc

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli-linux-x64-glibc@4701

@wasp.sh/wasp-cli-linux-x64-musl

npx https://pkg.pr.new/wasp-lang/wasp/@wasp.sh/wasp-cli-linux-x64-musl@4701

commit: 6a1b9cf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant