Open-Source Wikis

/

Solid

/

Packages

/

solid-ssr

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 renderStatic

The 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:

  1. Modules are evaluated cleanly per render — no globals leaking between pages.
  2. 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 --> Client

Build configuration

Each example owns a Rollup config that:

  1. Compiles the shared App.jsx with babel-preset-solid (configured for generate: "ssr", hydratable: true for the server build, and generate: "dom", hydratable: true for the client build).
  2. Resolves solid-js/web against the server condition for the server bundle.
  3. Outputs to lib/ (server entry) or public/ (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, and express (for the example servers). The published static/ runner depends only on node builtins.
  • Uses renderToStringAsync and renderToStream from solid-js/web — see solid-js/web server entry.
  • The ssg example is a useful starting point for SolidStart's "prerender" mode, though SolidStart proper lives in solidjs/solid-start.

Entry points for modification

  • Add a new strategy example: create packages/solid-ssr/examples/<name>/, add rollup.config.js and index.js, add build:example:<name> / start:example:<name> scripts to packages/solid-ssr/package.json, and add a row to the comparison table in README.md.
  • Change the static runner: packages/solid-ssr/static/index.js and writeToDisk.js. Be aware that the runner is spawned with node, 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.

solid-ssr – Solid wiki | Factory