Use with SSR
Static Extraction a.k.a. Server Side Rendering
Twind supports static extraction a.k.a. Server Side Rendering (SSR) out of the box.
Synchronous SSR
The following example assumes your app is using the tw
named export from twind
but the same logic can be applied to custom instances.
import { setup } from 'twind'
import { virtualSheet, getStyleTag } from 'twind/sheets'
const sheet = virtualSheet()
setup({ ...sharedOptions, sheet })
function ssr() {
// 1. Reset the sheet for a new rendering
sheet.reset()
// 2. Render the app
const body = renderTheApp()
// 3. Create the style tag with all generated CSS rules
const styleTag = getStyleTag(sheet)
// 4. Generate the response html
return `<!DOCTYPE html>
<html lang="en">
<head>${styleTag}</head>
<body>${body}</body>
</html>
`
}
In order to prevent harmful code injection on the web, a Content Security Policy (CSP) may be put in place. During server-side rendering, a cryptographic nonce (number used once) may be embedded when generating a page on demand:
// ... other code is the same as before ...
// Usage with webpack: https://webpack.js.org/guides/csp/
const styleTag = getStyleTag(sheet, { nonce: __webpack_nonce__ })
Asynchronous SSR
❗ Please note the
twind/server
bundle is Node.JS only. ❗ This is an experimental feature and only supported for Node.JS >=12. care and please report any issue you find. Consider using the synchronous API when ever possible due to the relatively expensive nature of the promise introspection API provided by V8. Async server side rendering is implemented using async_hooks. Callback-based APIs and event emitters may not work or need special handling.
import { setup } from 'twind'
import { asyncVirtualSheet, getStyleTag } from 'twind/server'
const sheet = asyncVirtualSheet()
setup({ ...sharedOptions, sheet })
async function ssr() {
// 1. Reset the sheet for a new rendering
sheet.reset()
// 2. Render the app
const body = await renderTheApp()
// 3. Create the style tag with all generated CSS rules
const styleTag = getStyleTag(sheet)
// 4. Generate the response html
return `<!DOCTYPE html>
<html lang="en">
<head>${styleTag}</head>
<body>${body}</body>
</html>
`
}
Streaming SSR
Supporting ReactDOM.renderToNodeStream and Vue.renderToStream is still on the roadmap...