Skip to content

docs: Node deployment via start.node emitted entry - #1638

Merged
ryansolid merged 4 commits into
v2-rebuildfrom
docs/start-node-entry
Sep 18, 2026
Merged

ryansolid merged 4 commits into
v2-rebuildfrom
docs/start-node-entry

Conversation

@ryansolid

@ryansolid ryansolid commented Sep 18, 2026

Copy link
Copy Markdown
Member

Documents the new @solidjs/vite-plugin option start.node (solidjs/solid-vite-plugin#366): with start: { node: true }, vite build emits dist/server/node.js next to dist/server/server.js, a complete Node server (static dist/client first, then handleRequest(request, { event: { nativeEvent: req } }), PORT/HOST from the environment, listener / createListener / serve exports). server.js, handleRequest, and the default { fetch } export are unchanged.

Changes per page

  • (3)building-apps/(7)deployment.mdx
    • Intro: Node host is now "the emitted dist/server/node.js" rather than the template's server.js.
    • Request handler section: one sentence after the Avoid/Prefer pair saying the emitted entry is the Prefer version; the Set-Cookie caution is attributed to the emitted entry.
    • ## Node rewritten: enable start.node (config block), pnpm build + node dist/server/node.js, PORT/HOST, the templates' start script, a bullet list of what the emitted entry does (static first with the cache headers, dot-segment and .. refusal; bridge behaviors; client-mode history fallback and endpoint routing; plain HTTP, compress/TLS at the proxy). The nativeEvent tip is kept and attributed to the emitted entry.
    • New ### Your own Node server: the listener / createListener(options) / serve(options) exports; http.createServer(listener); two Express recipes matching the plugin README (compression() + listener; express.static + createListener({ static: false })); one sentence each on static: false (also drops the client-mode history fallback) and event; the hand-written handleRequest bridge demoted to a last resort with a pointer to the requirements.
    • Preview section: "reserve start for the emitted Node server".
    • Common problems: new Cannot find module 'dist/server/node.js' entry (option not set); the existing server.js entry is kept and cross-referenced; the Set-Cookie entry is re-attributed.
    • Recap: the Node bullet now reads "Set start.node and run node dist/server/node.js...".
  • reference/(5)vite-plugin-solid/(2)start.mdx: node?: boolean added to the StartOptions type; new ### node option in the page's format with the emitted module's exports as a ts signature block; dist/server/node.js added to the SSR start mode build outputs and the server-functions/client-mode note.
  • (1)getting-started/(1)project-shapes.mdx: "The template's server.js is the Node version of that" replaced with the start: { node: true } / dist/server/node.js statement.
  • (6)migration/(2)from-solid-start.mdx: "The pinned templates include a verified Node adapter" replaced with the start.node instruction.

Not changed (audited, still true): app-structure, rendering-and-ssr, choose-a-rendering-mode, modules only say "a request handler in dist/server"; the dist/server/server.js-as-handler statements everywhere stay as they are.

Verified against solidjs/solid-vite-plugin#366 (ab03656)

Checked against src/node-entry/index.ts, src/ssr/index.ts, src/http.ts, the StartOptions.node docblock, the README Node section, .changeset/start-node-entry.md, and the node mode of examples/start-ssr/test/run.mjs and examples/start-client/test/run.mjs.

Confirmed as written: PORT default 3000 and HOST; listens only when run directly (path.resolve(process.argv[1]) === import.meta.filename), importing does not listen; listener is createListener() and includes static serving; /assets/* (build.assetsDir) Cache-Control: public, max-age=31536000, immutable; .. cannot escape the client directory; HEAD answered without a body; bridge streams non-GET/HEAD bodies, splits set-cookie, aborts on client disconnect, applies backpressure; getRequestEvent().nativeEvent is the IncomingMessage; client start mode with serverFunctions gets index.html history fallback for HTML-accepting GETs plus the endpoint; server.js byte-identical with and without the option.

Corrected:

  • Non-hashed files: must-revalidate + Last-Modifiedpublic, max-age=0, must-revalidate + Last-Modified.
  • Added: dot-segment paths (.vite/manifest.json) are never served, matching vite preview.
  • Exports: listener and serve()listener, createListener({ static?, event? }), serve({ port?, host?, static?, event? }) returning the http.Server; the reference now lists the signatures.
  • Warnings: "warns and ignores node when the build writes no server bundle" → warns and emits nothing with start.external and in client mode without serverFunctions; emission is ssr-environment only and requires server.js in the bundle. (There is no separate "start off" warning in the code; node lives inside start.)
  • Added: errors log to console.error and answer 500; the entry speaks plain HTTP, so TLS and compression belong at the proxy/CDN or in Express.
  • Added: root-relative base prefixes the static paths.

Depends on

Un-draft when both are in.

Checks

pnpm check:lint, pnpm check:types, pnpm lint:tone, prettier --check on the touched files, and pnpm build pass. pnpm check:examples was not run: it type-checks ts blocks against a sibling plugin checkout, and start: { node: true } will not type-check until the plugin ships the option.

Document the @solidjs/vite-plugin start.node option: vite build emits
dist/server/node.js, a complete Node server (static dist/client first,
then handleRequest with event.nativeEvent), so the Node bridge no longer
lives in a hand-maintained server.js in each project.

- Deployment: rewrite the Node section around start.node and
  node dist/server/node.js (PORT/HOST, the start script, what the emitted
  entry does), add 'Your own Node server' for the listener export and a
  hand-written bridge, re-attribute the Set-Cookie caution and the
  nativeEvent tip, add a Common problems entry for a missing node.js,
  update the intro and Recap.
- StartOptions reference: add node to the type and options, and to the
  build outputs and server-functions notes.
- Project shapes, Migrate from SolidStart: replace the template-provided
  server.js statements.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@netlify

netlify Bot commented Sep 18, 2026

Copy link
Copy Markdown

Deploy Preview for solid-docs-v2 ready!

Name Link
🔨 Latest commit 85365bc
🔍 Latest deploy log https://app.netlify.com/projects/solid-docs-v2/deploys/6aacfa7701dc1f00088dca26
😎 Deploy Preview https://deploy-preview-1638--solid-docs-v2.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

autofix-ci Bot and others added 3 commits September 18, 2026 07:52
…cipes

- Cache-Control for non-hashed files is public, max-age=0, must-revalidate;
  hashed files are those under build.assetsDir.
- Dot-segment paths (.vite/manifest.json) are refused, as in vite preview.
- Exports are listener, createListener({ static?, event? }), and
  serve({ port?, host?, static?, event? }) returning the http.Server;
  the reference lists the signatures.
- Warnings: start.external, and client mode without serverFunctions;
  emission is ssr-environment only and requires server.js in the bundle.
- Deployment: Express recipes (compression + listener; express.static +
  createListener({ static: false })), the plain-HTTP/proxy stance, and the
  hand-written handleRequest bridge demoted to a last resort.

Co-authored-by: Cursor <cursoragent@cursor.com>
@ryansolid
ryansolid marked this pull request as ready for review September 18, 2026 15:37
@ryansolid
ryansolid merged commit e1b24a4 into v2-rebuild Sep 18, 2026
8 checks passed
@ryansolid
ryansolid deleted the docs/start-node-entry branch September 18, 2026 15:43
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