--- name: solid-core-rendering description: "SolidJS rendering: render for client apps, hydrate for SSR, renderToString for server rendering, renderToStream for streaming, isServer checks." metadata: globs: - "**/entry-*.tsx" - "**/*render*" --- # SolidJS Rendering Utilities Complete guide to rendering SolidJS applications. Understand client-side rendering, SSR, hydration, and streaming. ## render - Client-Side Rendering Mount your Solid app to the DOM. Essential browser entry point for SPAs. ```tsx import { render } from "solid-js/web"; const dispose = render(() => , document.getElementById("app")!); // Later, unmount dispose(); ``` **Key points:** - First argument must be a **function** (not JSX directly) - Element should be empty (render appends, dispose removes all) - Returns dispose function to unmount **Correct usage:** ```tsx // ✅ Correct - function render(() => , element); // ❌ Wrong - JSX directly render(, element); ``` ## hydrate - SSR Hydration Hydrate server-rendered HTML with client-side code. Essential for SSR apps. ```tsx import { hydrate } from "solid-js/web"; const dispose = hydrate(() => , document.getElementById("app")!); ``` **Key points:** - Rehydrates existing DOM - Matches server-rendered structure - Attaches interactivity - Used in SSR applications **Options:** ```tsx hydrate(() => , element, { renderId: "app", // Optional render ID owner: undefined, // Optional owner context }); ``` ## renderToString - Server Rendering Render components to HTML string for SSR. ```tsx import { renderToString } from "solid-js/web"; const html = renderToString(() => ); // Returns: "
...
" ``` **Use cases:** - SSR initial render - Static site generation - Email templates - Server-side HTML generation ## renderToStringAsync - Async Rendering Render components with async data to HTML string. ```tsx import { renderToStringAsync } from "solid-js/web"; const html = await renderToStringAsync(() => ); // Waits for async resources ``` **Use cases:** - SSR with async data - Resources and Suspense - Async components ## renderToStream - Streaming SSR Stream HTML to client for faster time-to-first-byte. ```tsx import { renderToStream } from "solid-js/web"; const stream = renderToStream(() => ); // Pipe to response stream.pipeTo(response); ``` **Benefits:** - Faster initial render - Progressive HTML delivery - Better perceived performance ## HydrationScript / generateHydrationScript Bootstrap hydration before Solid runtime loads. ```tsx import { HydrationScript, generateHydrationScript } from "solid-js/web"; // As component (JSX) // As string (manual HTML) const script = generateHydrationScript({ nonce, eventNames: ["click", "input"], }); ``` **Purpose:** - Sets up hydration on client - Required for SSR apps - Place once in `` or before closing `` ## isServer - Environment Check Check if code is running on server. ```tsx 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 server/client code - Environment-specific logic - Avoiding browser APIs on server ## Common Patterns ### Client Entry Point ```tsx // entry-client.tsx import { render } from "solid-js/web"; import App from "./App"; render(() => , document.getElementById("app")!); ``` ### SSR Entry Point ```tsx // entry-server.tsx import { renderToString, generateHydrationScript } from "solid-js/web"; import App from "./App"; export default function handler(req, res) { const html = renderToString(() => ); res.send(` ${generateHydrationScript()}
${html}
`); } ``` ### Client Hydration ```tsx // entry-client.tsx import { hydrate } from "solid-js/web"; import App from "./App"; hydrate(() => , document.getElementById("app")!); ``` ### Streaming SSR ```tsx import { renderToStream } from "solid-js/web"; export default async function handler(req, res) { const stream = renderToStream(() => ); res.setHeader("Content-Type", "text/html"); stream.pipeTo(res); } ``` ### Environment-Specific Code ```tsx import { isServer } from "solid-js/web"; function Component() { if (isServer) { // Server-only initialization return
Server rendered
; } // Client-only code const [mounted, setMounted] = createSignal(false); onMount(() => setMounted(true)); return
Client: {mounted()}
; } ``` ## Best Practices 1. **Always use function form:** - `render(() => , element)` - Not `render(, element)` 2. **Empty mount element:** - Element should be empty - Render appends, dispose removes all 3. **Hydration matching:** - Server and client must match - Same structure and content 4. **Use isServer checks:** - Avoid browser APIs on server - Conditional logic when needed 5. **Streaming for performance:** - Use renderToStream for SSR - Faster time-to-first-byte ## Summary - **render**: Client-side mounting - **hydrate**: SSR hydration - **renderToString**: Server HTML generation - **renderToStringAsync**: Async server rendering - **renderToStream**: Streaming SSR - **HydrationScript / generateHydrationScript**: Hydration setup - **isServer**: Environment detection