{"id":10789,"library":"emotion-server","title":"Emotion Server-Side Rendering Utilities","description":"@emotion/server is a critical package within the Emotion CSS-in-JS ecosystem, primarily designed to facilitate efficient server-side rendering (SSR) of styled React applications. Its core functionality involves extracting and inlining only the 'critical CSS' required for the initial page load, thereby preventing flashes of unstyled content (FOUC) and improving perceived performance. The package is part of the Emotion v11 stable release, which introduced significant TypeScript improvements and internal shifts to React Hooks. Emotion maintains a consistent, modular release cadence across its packages, with frequent patch updates and coordinated minor/major versions. A key differentiator is its deep integration with the `@emotion/react` and `@emotion/cache` packages, providing robust and performant solutions for complex SSR setups, including support for React's streaming APIs, though this often requires more advanced configurations.","status":"active","version":"11.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/emotion-js/emotion/tree/master/packages/emotion-server","tags":["javascript","styles","emotion","react","css","css-in-js","ssr","server-side-rendering","typescript"],"install":[{"cmd":"npm install emotion-server","lang":"bash","label":"npm"},{"cmd":"yarn add emotion-server","lang":"bash","label":"yarn"},{"cmd":"pnpm add emotion-server","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Provides the React context and `CacheProvider` essential for Emotion's SSR and style injection. Emotion v11 renamed `@emotion/core` to `@emotion/react`.","package":"@emotion/react","optional":false},{"reason":"Required for creating and managing the Emotion style cache, which is fundamental to server-side style extraction.","package":"@emotion/cache"}],"imports":[{"note":"This is the primary function for extracting critical CSS from a rendered React string. While CommonJS `require` can sometimes work via transpilation, direct ESM `import` is the standard for modern Node.js and bundled environments.","wrong":"const { extractCritical } = require('@emotion/server');","symbol":"extractCritical","correct":"import { extractCritical } from '@emotion/server';"},{"note":"Used for React 18+ streaming SSR to inject styles into a Node.js stream. Requires careful integration with `ReactDOMServer.renderToNodeStream` or `renderToPipeableStream`.","wrong":"const { renderStylesToNodeStream } = require('@emotion/server');","symbol":"renderStylesToNodeStream","correct":"import { renderStylesToNodeStream } from '@emotion/server';"},{"note":"Essential for providing an Emotion cache to your React tree during SSR. Emotion v11 renamed `@emotion/core` to `@emotion/react`. Incorrect package or missing `CacheProvider` leads to errors.","wrong":"import { CacheProvider } from '@emotion/core';","symbol":"CacheProvider","correct":"import { CacheProvider } from '@emotion/react';"},{"note":"`createCache` is a default export from `@emotion/cache` and is used to instantiate a new Emotion cache for each server request. Since Emotion v11, the `key` option is mandatory when creating a custom cache.","wrong":"import { createCache } from '@emotion/cache'; // If default export\nconst createCache = require('@emotion/cache'); // Missing .default for default export","symbol":"createCache","correct":"import createCache from '@emotion/cache';"}],"quickstart":{"code":"import ReactDOMServer from 'react-dom/server';\nimport { CacheProvider } from '@emotion/react';\nimport createCache from '@emotion/cache';\nimport { extractCritical } from '@emotion/server';\nimport { css } from '@emotion/react';\n\n// A simple Emotion-styled React component\nconst MyStyledComponent = () => (\n  <div\n    css={css`\n      color: hotpink;\n      background-color: lightblue;\n      padding: 1rem;\n      border-radius: 8px;\n      &:hover {\n        color: white;\n      }\n    `}\n  >\n    Hello from Emotion SSR!\n  </div>\n);\n\n// Create a new Emotion cache for the server request\n// The 'key' option is mandatory since Emotion v11\nconst cache = createCache({ key: 'my-app' });\n\n// Render the component to a string and extract critical CSS\nconst { html, css: criticalCss, ids } = extractCritical(\n  ReactDOMServer.renderToString(\n    <CacheProvider value={cache}>\n      <MyStyledComponent />\n    </CacheProvider>\n  )\n);\n\nconsole.log('--- Critical CSS ---');\nconsole.log(criticalCss);\nconsole.log('\\n--- Rendered HTML ---');\nconsole.log(`<style data-emotion=\"${cache.key}-${ids.join(' ')}\">${criticalCss}</style>${html}`);\n\n// In a real application, 'criticalCss' would be injected into the <head> of the HTML document.\n// The 'ids' should also be passed to the client for proper hydration.\n// Example of how to integrate into a full HTML document (simplified):\nconst fullHtml = `\n  <!DOCTYPE html>\n  <html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Emotion SSR Example</title>\n    <style data-emotion=\"${cache.key}-${ids.join(' ')}\">${criticalCss}</style>\n  </head>\n  <body>\n    <div id=\"root\">${html}</div>\n    <script>\n      // On the client, hydrate with the same cache key and potentially call emotion/css hydrate function\n      // import { hydrate } from '@emotion/css';\n      // import createCache from '@emotion/cache';\n      // const cache = createCache({ key: 'my-app' });\n      // hydrate(${JSON.stringify(ids)});\n      // ReactDOMClient.hydrateRoot(document.getElementById('root'), <CacheProvider value={cache}><MyStyledComponent /></CacheProvider>);\n    </script>\n  </body>\n  </html>\n`;\nconsole.log('\\n--- Full HTML Structure (simplified) ---');\nconsole.log(fullHtml);","lang":"typescript","description":"Demonstrates how to use `emotion-server`'s `extractCritical` function with React's `renderToString` to extract and inline critical CSS during server-side rendering, ensuring proper `CacheProvider` setup for Emotion v11."},"warnings":[{"fix":"Review Emotion's v11 migration guide. Update package names and ensure `createCache({ key: 'your-app-key' })` is used. Use the Emotion ESLint plugin with codemods to automate some renames.","message":"Migrating from Emotion v10 to v11 involves significant breaking changes, including package renames (e.g., `@emotion/core` to `@emotion/react`), and a mandatory `key` option when initializing Emotion's cache via `createCache`. Ensure all Emotion-related packages are upgraded to compatible v11 versions.","severity":"breaking","affected_versions":">=11.0.0"},{"fix":"Always wrap your top-level component with `<CacheProvider value={cache}>` during SSR. Ensure a unique cache instance is created for each request on the server. On the client, ensure proper hydration logic is in place, often by calling `hydrate(ids)` if using `extractCritical`.","message":"Incorrect or missing `CacheProvider` setup on the server or a mismatch between server and client-side generated styles can lead to hydration errors (e.g., UI differences or style re-insertion). Each server render should typically use a new `EmotionCache` instance.","severity":"gotcha","affected_versions":">=11.0.0"},{"fix":"If experiencing issues with complex selectors, switch to the 'advanced approach' using `extractCritical` with `CacheProvider` on the server and ensure the extracted styles are correctly injected into the `<head>` of your HTML document.","message":"Emotion's 'default approach' for SSR (without explicit critical extraction) can interfere with `:nth-child` or similar selectors due to style tags being inserted directly into the markup. The advanced approach using `extractCritical` or `createEmotionServer` avoids this.","severity":"gotcha","affected_versions":">=10.0.0"},{"fix":"Prefer `extractCritical` for most SSR scenarios where you render to a string and need to inject styles. For React 18 streaming, use `renderStylesToNodeStream` in conjunction with React's streaming APIs.","message":"The `renderStylesToString` function from `@emotion/server` is largely superseded by `extractCritical` for comprehensive critical CSS extraction and `renderStylesToNodeStream` for React 18 streaming. While it still works, `extractCritical` provides more control over the extracted CSS and IDs.","severity":"deprecated","affected_versions":"<=11.0.0"},{"fix":"Consult detailed documentation or framework-specific guides (e.g., Next.js, Gatsby) for React 18 streaming SSR with Emotion. The `renderStylesToNodeStream` should be piped after React's stream.","message":"Integrating Emotion with React 18's streaming SSR (`renderToPipeableStream`) is significantly more complex than traditional `renderToString`. `emotion-server` provides `renderStylesToNodeStream`, but advanced setups often require custom transform streams or specific framework integrations.","severity":"gotcha","affected_versions":">=11.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure the same Emotion cache key and configuration are used on both server and client. Verify that `CacheProvider` wraps your application during SSR. If using `extractCritical`, ensure the extracted `ids` are passed to the client and `hydrate(ids)` is called.","cause":"Client-side React is trying to hydrate a DOM tree that differs from the server-rendered HTML, often due to mismatched Emotion styles, incorrect cache setup, or missing `hydrate` call.","error":"Error: Hydration failed because the initial UI does not match what was rendered on the server."},{"fix":"Ensure `createCache` is called with the `key` option and potentially a custom `container` or `stylisPlugins` if non-browser defaults are an issue. Creating a cache per request on the server also helps isolate styles.","cause":"This typically occurs when `createCache` from `@emotion/cache` is invoked directly in a Node.js (server) environment without providing a suitable `container` or `stylisPlugins` option if browser-specific APIs are implicitly accessed.","error":"ReferenceError: navigator is not defined"},{"fix":"Double-check that `createCache` is correctly called, and the resulting `cache` object is passed to `<CacheProvider value={cache}>` wrapping your application on the server. Verify that all Emotion-related packages are compatible versions.","cause":"This error often indicates that the Emotion cache instance or the `CacheProvider` is not correctly set up or accessible within the React component tree during SSR.","error":"TypeError: Cannot read properties of undefined (reading 'sheet')"},{"fix":"Ensure that your entire application, especially the root component being rendered server-side, is wrapped within `<CacheProvider value={cache}>` where `cache` is an instance created by `createCache`.","cause":"The Emotion context, provided by `CacheProvider`, is missing from the component tree, preventing Emotion components from accessing the necessary cache.","error":"Error: @emotion/react's CacheProvider was not found."}],"ecosystem":"npm"}