Agent skill
solid-core-rendering-ssr
SolidJS rendering and SSR: render() for client, hydrate() for SSR hydration, renderToString/renderToStream for server rendering, isServer check.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/solid-core-rendering-ssr
SKILL.md
Rendering and SSR
Client-Side Rendering
render()
Mounts Solid app to DOM. Browser entry point for SPAs.
import { render } from "solid-js/web";
const dispose = render(() => <App />, document.getElementById("app")!);
Critical: First argument must be a function, not JSX directly.
// ✅ Correct
render(() => <App />, element)
// ❌ Wrong - calls App before render sets up tracking
render(<App />, element)
Returns dispose function to unmount app:
const dispose = render(() => <App />, element);
// Later...
dispose();
Server-Side Rendering
hydrate()
Hydrates server-rendered HTML. Client entry point for SSR apps.
import { hydrate } from "solid-js/web";
const dispose = hydrate(() => <App />, document.getElementById("app")!);
Attempts to rehydrate DOM that was already rendered on server. Must match server output.
renderToString()
Renders component to HTML string (synchronous).
import { renderToString } from "solid-js/web";
const html = renderToString(() => <App />);
renderToStringAsync()
Renders component to HTML string (asynchronous). Handles Suspense boundaries.
import { renderToStringAsync } from "solid-js/web";
const html = await renderToStringAsync(() => <App />);
Use when:
- App has async data fetching
- Suspense boundaries need resolution
- Server-side data loading required
renderToStream()
Streams HTML to response. Progressive rendering for better performance.
import { renderToStream } from "solid-js/web";
const stream = renderToStream(() => <App />);
// Pipe to response
stream.pipeTo(response.writable);
Benefits:
- Faster Time to First Byte (TTFB)
- Progressive HTML delivery
- Better perceived performance
HydrationScript
Bootstrap hydration before Solid runtime loads. Captures events before JS loads.
import { HydrationScript, generateHydrationScript } from "solid-js/web";
// As component (JSX)
<HydrationScript
nonce={nonce}
eventNames={["click", "input"]}
/>
// As function (HTML string)
const script = generateHydrationScript({
nonce: nonce,
eventNames: ["click", "input"]
});
Options:
nonce: CSP nonce for script tageventNames: Events to capture before JS loads (default:["click", "input"])
Use case: Progressive enhancement - capture user interactions before hydration completes.
Server Detection
isServer
Check if code is running on server.
import { isServer } from "solid-js/web";
if (isServer) {
// Server-only code
console.log("Running on server");
} else {
// Client-only code
console.log("Running on client");
}
Use cases:
- Conditional imports
- Server-only initialization
- Platform-specific code
Note: Bundlers eliminate dead code based on this constant.
DEV
Development-only features. Removed in production builds.
import { DEV } from "solid-js";
import { isServer } from "solid-js/web";
// Only runs in development (client-side)
if (DEV && !isServer) {
console.log("Development mode");
}
Use cases:
- Development debugging
- Dev-only features
- Library development
- Conditional code for dev/prod
Note: DEV is always defined on server, so combine with isServer check for client-only dev code.
SSR Best Practices
-
Match server and client output:
- Use
hydrate()with matching server-rendered HTML - Ensure component order is identical
- Use
-
Handle async data:
- Use
renderToStringAsync()for Suspense - Preload data on server when possible
- Use
-
Streaming:
- Use
renderToStream()for better performance - Progressive rendering improves TTFB
- Use
-
Avoid hydration mismatches:
- Don't use
Math.random()orDate.now()in render - Use
createUniqueId()for stable IDs - Check
isServerfor platform-specific code
- Don't use
-
NoHydration for static content:
- Wrap static content in
<NoHydration>to skip hydration - Reduces client-side JavaScript
- Wrap static content in
Example: Full SSR Setup
Server (entry-server.tsx):
import { renderToStream } from "solid-js/web";
import App from "./App";
export async function handler(request: Request) {
const stream = renderToStream(() => <App />);
return new Response(stream, {
headers: { "Content-Type": "text/html" }
});
}
Client (entry-client.tsx):
import { hydrate } from "solid-js/web";
import App from "./App";
hydrate(() => <App />, document.getElementById("app")!);
Didn't find tool you were looking for?