solidjs/solid
solid-ssr
Active contributors: Ryan Carniato, Damian Tarnawski
solid-ssr is the package that bundles a small static-site generator for Solid plus four runnable example servers (async, ssr, ssg, stream) that demonstrate the four supported render strategies.
Purpose
solid-js/web's server entry already exposes renderToString, renderToStringAsync, and renderToStream (see solid-js/web server entry). solid-ssr is a thin layer on top that:
- Provides
renderStatic(...)— a runner that spawns child processes to render a list of pages and write each result to disk. Used for static-site generation. - Ships four canonical example apps in
packages/solid-ssr/examples/so users can copy the right rollup + server setup for their use case.
Directory layout
packages/solid-ssr/
├── package.json # exports map, build/start scripts per example
├── README.md # comparison table for the four strategies
├── CHANGELOG.md
├── static/ # the published `solid-ssr/static` runner
│ ├── index.js # renderStatic implementation
│ ├── index.cjs # CJS variant
│ └── writeToDisk.js # the per-page worker spawned by renderStatic
└── examples/
├── shared/ # the App component & isomorphic shared code
├── async/ # async-rendering example (renderToStringAsync)
├── ssr/ # synchronous SSR example (renderToString)
├── stream/ # streaming example (renderToStream)
└── ssg/ # static generation, uses renderStaticThe static/ folder is what gets published. The examples/ folder is .npmignored but lives in the repo for documentation and integration testing.
Key abstractions
| Symbol | Source | Description |
|---|---|---|
renderStatic(config) |
packages/solid-ssr/static/index.js |
Default export. Accepts an array of { entry, output, url } objects; spawns a Node child process per entry to render the page and write the result. |
writeToDisk.js |
packages/solid-ssr/static/writeToDisk.js |
The runner spawned by renderStatic. Imports the entry, calls its default export with { url }, and writes the resulting HTML to output. |
| Each example server | packages/solid-ssr/examples/<name>/index.js |
A small Express app demonstrating one of the four render strategies. |
How it works
renderStatic
import { execFile } from "child_process";
async function run({ entry, output, url }) {
const { stdout, stderr } = await exec("node", [pathToRunner, entry, output, url]);
...
}
export default async function renderStatic(config) {
if (Array.isArray(config)) await Promise.all(config.map(run));
else await run(config);
}renderStatic does not import the entry into the current process; it spawns a fresh node writeToDisk.js <entry> <output> <url> for each page. Two reasons:
- Modules are evaluated cleanly per render — no globals leaking between pages.
- Errors in one page's render do not poison the others; they fail loudly with non-zero exit codes.
The pattern fits well with the ssg example which generates a tab-style navigation tree; each tab becomes its own HTML file.
Example server: synchronous SSR
packages/solid-ssr/examples/ssr/index.js:
import express from "express";
import { renderToString } from "solid-js/web";
import App from "../shared/src/components/App";
const app = express();
app.use(express.static(...));
app.get("*", (req, res) => {
let html;
try {
html = renderToString(() => <App url={req.url} />);
} catch (err) {
console.error(err);
} finally {
res.send(html);
}
});
app.listen(3000);The other three examples follow the same shape, swapping renderToString for renderToStringAsync (async/), renderToStream (stream/), or renderStatic (ssg/export.js).
The packages/solid-ssr/README.md table compares the trade-offs:
| Folder | Strategy | When data loads | Render function |
|---|---|---|---|
ssr/ |
Synchronous SSR | Client (after hydration) | renderToString |
async/ |
Async SSR | Server, at request time | renderToStringAsync |
stream/ |
Streaming | Server, progressively | renderToStream |
ssg/ |
Static generation | Server, at build time | renderToStringAsync (via renderStatic) |
graph LR
Client[Browser request] --> Server[Express route]
Server -->|"renderToString"| Sync[ssr/]
Server -->|"renderToStringAsync"| Async[async/]
Server -->|"renderToStream"| Stream[stream/]
Build[Build step] -->|"renderStatic"| SSG[ssg/]
Sync --> Client
Async --> Client
Stream --> Client
SSG -->|.html files on disk| Static[CDN]
Static --> ClientBuild configuration
Each example owns a Rollup config that:
- Compiles the shared
App.jsxwithbabel-preset-solid(configured forgenerate: "ssr", hydratable: truefor the server build, andgenerate: "dom", hydratable: truefor the client build). - Resolves
solid-js/webagainst the server condition for the server bundle. - Outputs to
lib/(server entry) orpublic/(static asset).
The package.json scripts (build:example:ssr, start:example:ssr, etc.) wrap these per example.
Key source files
| File | Purpose |
|---|---|
packages/solid-ssr/static/index.js |
The exported renderStatic function. |
packages/solid-ssr/static/writeToDisk.js |
Per-page worker. |
packages/solid-ssr/examples/shared/src/components/App.js |
The shared isomorphic app used by all four examples. |
packages/solid-ssr/examples/<name>/rollup.config.js |
Per-strategy Rollup configs. |
packages/solid-ssr/examples/<name>/index.js |
Per-strategy server entry. |
packages/solid-ssr/README.md |
The comparison table that shows when to pick each strategy. |
Integration points
- Depends on
solid-js,babel-preset-solid, andexpress(for the example servers). The publishedstatic/runner depends only onnodebuiltins. - Uses
renderToStringAsyncandrenderToStreamfromsolid-js/web— seesolid-js/webserver entry. - The
ssgexample is a useful starting point for SolidStart's "prerender" mode, though SolidStart proper lives insolidjs/solid-start.
Entry points for modification
- Add a new strategy example: create
packages/solid-ssr/examples/<name>/, addrollup.config.jsandindex.js, addbuild:example:<name>/start:example:<name>scripts topackages/solid-ssr/package.json, and add a row to the comparison table inREADME.md. - Change the static runner:
packages/solid-ssr/static/index.jsandwriteToDisk.js. Be aware that the runner is spawned withnode, so any breaking change to the CLI signature affects every consumer. - Update the shared example app:
packages/solid-ssr/examples/shared/. Change shape carefully — every example bundle re-exports it.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.