Stream-based CSS inlining functionality that creates Node.js transform streams for inlining critical CSS with HTML streaming, ideal for large pages and improved performance through progressive rendering.
Creates a Node.js transform stream that inlines critical CSS as HTML flows through it, enabling progressive rendering and better performance for large applications.
/**
* Creates a Node.js transform stream for inlining critical CSS
* @returns Transform stream that inlines critical CSS as HTML passes through
*/
function renderStylesToNodeStream(): NodeJS.ReadWriteStream;Usage Examples:
import React from "react";
import { renderToNodeStream } from "react-dom/server";
import { renderStylesToNodeStream } from "@emotion/server";
import styled from "@emotion/styled";
const Button = styled.button`
background: blue;
color: white;
padding: 10px 20px;
`;
const App = () => <Button>Click me</Button>;
// Create the CSS inlining stream
const cssStream = renderStylesToNodeStream();
// Pipe React's stream through the CSS stream
renderToNodeStream(<App />)
.pipe(cssStream)
.pipe(process.stdout);
// Output will include inlined <style> tags as the HTML streamsThe stream uses a sophisticated pipeline built on:
Internal Stream Flow:
HTML Input → Tokenizer → CSS Injector → HTML Output with StylesBasic Streaming Response:
import express from "express";
import React from "react";
import { renderToNodeStream } from "react-dom/server";
import { renderStylesToNodeStream } from "@emotion/server";
const app = express();
app.get("/", (req, res) => {
res.writeHead(200, { "Content-Type": "text/html" });
// Write HTML head
res.write(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Streaming App</title>
</head>
<body>
<div id="root">`);
// Stream the React app with CSS inlining
const cssStream = renderStylesToNodeStream();
renderToNodeStream(<App />)
.pipe(cssStream)
.pipe(res, { end: false });
// Close HTML body after streaming completes
cssStream.on("end", () => {
res.write(`</div>
</body>
</html>`);
res.end();
});
});Custom Stream Processing:
import { Transform } from "stream";
import { renderStylesToNodeStream } from "@emotion/server";
// Create custom transform stream for additional processing
const customProcessor = new Transform({
transform(chunk, encoding, callback) {
// Add custom processing logic here
const processed = chunk.toString().replace(/data-testid="[^"]*"/g, "");
callback(null, processed);
}
});
// Chain multiple streams
renderToNodeStream(<App />)
.pipe(renderStylesToNodeStream())
.pipe(customProcessor)
.pipe(outputStream);Error Handling with Streams:
import { renderToNodeStream } from "react-dom/server";
import { renderStylesToNodeStream } from "@emotion/server";
const streamWithErrorHandling = (app, res) => {
const cssStream = renderStylesToNodeStream();
const reactStream = renderToNodeStream(app);
// Handle stream errors
reactStream.on("error", (error) => {
console.error("React stream error:", error);
res.statusCode = 500;
res.end("Server error occurred");
});
cssStream.on("error", (error) => {
console.error("CSS stream error:", error);
res.statusCode = 500;
res.end("CSS processing error");
});
// Pipe streams
reactStream.pipe(cssStream).pipe(res);
};The stream processes HTML tokens and:
<style> tags when new Emotion styles are detectedCustom Cache with Streaming:
import createEmotionServer from "@emotion/server/create-instance";
import createCache from "@emotion/cache";
// Create cache with custom configuration
const cache = createCache({
key: "streaming",
nonce: "stream-nonce-123"
});
const { renderStylesToNodeStream } = createEmotionServer(cache);
// Use custom cache for streaming
const streamWithCustomCache = renderStylesToNodeStream();Memory Efficiency:
Progressive Rendering:
Backpressure Handling:
const cssStream = renderStylesToNodeStream();
// Monitor stream events
cssStream.on("pipe", (src) => {
console.log("Stream piped from:", src.constructor.name);
});
cssStream.on("data", (chunk) => {
console.log("Processed chunk:", chunk.length, "bytes");
});
cssStream.on("end", () => {
console.log("CSS stream processing completed");
});
cssStream.on("close", () => {
console.log("CSS stream closed");
});