Repository navigation
feat(node): let a server supply the ASSETS that serve the client build - #749
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The generated Node app (
dist/ssr/app.js) always serves the client build fromdist/client, found relative to the emitted chunk. A server that embeds the client build has no such directory. A Node single executable application and abun build --compileexecutable are two examples. In that case the page renders without its script tags, because the manifest is fetched through the filesystemASSETS, and it never hydrates. Today the only workarounds are settingglobalThis.__VITE_MANIFEST__and routing/assets/*in front of the app.We hit this shipping a Void app as one executable to Raspberry Pi menu boards, where a release is a single file and an update is replacing it.
What changes
ASSETS.app.jsnow uses anASSETSobject (with afetch(request)method) passed in the Hono env, and otherwise falls back to thedist/clientprovider as before. The supplied object serves/assets/*, and it reaches the routes asenv.ASSETS. So the manifest, hydration tags andpublic/files all go through it.ASSETSnever resolvesdist/client, and no longer logsserveStatic: root path … is not foundat startup.index.js,vite previewand the prerender runner pass noASSETS, and behave as before.Tests
pages-target-assets.test.ts, for the Node and Bun targets. It movesdist/clientaway and starts a server that suppliesASSETSfrom the moved copy. It asserts that every script on the page is served by the supplied provider, thatpublic/files and API routes still work, and that nothing warns about a missing client directory. Without the change, it fails: the page has no script tags.pages-target-assets.test.ts: 8 passed on Node and Bun 1.4.4; Deno is not installed here, so its 4 were skipped and the new test is not run for it.compile.test.tsandplugin-routing.test.ts: pass.voidtypecheck,vp fmtandvp lint: clean.Also checked by hand, each executable run from an empty directory:
bun build --compileexecutable (client files embedded throughtype: "file"imports), each passingASSETSas in the new docs: the page had its script tags, every asset was served from inside the binary, and nothing warned at startup.__VITE_MANIFEST__workaround: the same app as a Node SEA hydrated in Chrome, and cross-built for linux-arm64 it ran on a Raspberry Pi 400 (Debian trixie), ready in 366 ms.Docs
docs/integrations/nodejs-bun-deno.md: a short "Serving the client build from somewhere else" section, with anode:seaexample and a Bun one (embedding withtype: "file"imports, and passingserversogetConnInfo()keeps working).packages/void/AGENTS.md: one sentence on the override.