CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-react-server-dom-webpack

React Server Components bindings for DOM using Webpack, enabling server-side rendering with streaming support and client-server communication.

Pending
Overview
Eval results
Files

nodejs-integration.mddocs/

Node.js Integration

Node.js-specific utilities for server component module loading, directive processing, and runtime integration with React Server Components.

Capabilities

Module Registration

Registers Node.js module compilation hooks to automatically process "use client" and "use server" directives during module loading.

/**
 * Registers Node.js module hooks for directive processing
 * Hooks into the Node.js module system to handle RSC directives
 */
function register(): void;

Usage Examples:

// Register hooks before importing any server components
const register = require("react-server-dom-webpack/node-register");
register();

// Now you can import modules with directives
const ServerComponent = require("./ServerComponent"); // Contains "use server"
const ClientComponent = require("./ClientComponent"); // Contains "use client"

Package.json Integration:

{
  "scripts": {
    "dev": "node -r react-server-dom-webpack/node-register src/server.js",
    "start": "node --require react-server-dom-webpack/node-register dist/server.js"
  }
}

Programmatic Registration:

// server.js
require("react-server-dom-webpack/node-register")();

// Import React Server Components after registration
const { renderToPipeableStream } = require("react-server-dom-webpack/server.node");
const App = require("./App"); // Can contain RSC directives

function handleRequest(req, res) {
  const { pipe } = renderToPipeableStream(<App />, clientManifest);
  pipe(res);
}

Directive Processing

The registration system automatically processes modules containing RSC directives:

"use client" Directive Processing

Files with "use client" are converted to client module proxies:

// components/Button.js
"use client";

import { useState } from "react";

export function Button({ children, onClick }) {
  const [loading, setLoading] = useState(false);
  // ... component implementation
}

// After processing, exports become client module proxies
// that reference the client-side bundle

"use server" Directive Processing

Files with "use server" have their functions registered as server references:

// actions/userActions.js
"use server";

export async function updateUser(userData) {
  // This function is registered as a server reference
  return await database.users.update(userData);
}

export async function deleteUser(userId) {
  // This function is also registered as a server reference
  return await database.users.delete(userId);
}

// After processing, functions can be called from client components

Module Loading Patterns

Different patterns for loading and using the registration system:

Early Registration Pattern

// server/index.js
// Register before any imports
require("react-server-dom-webpack/node-register")();

// Safe to import RSC modules after registration
const express = require("express");
const { renderToPipeableStream } = require("react-server-dom-webpack/server.node");
const App = require("../components/App");

const app = express();

app.get("/", (req, res) => {
  const { pipe } = renderToPipeableStream(<App />, clientManifest);
  res.setHeader("Content-Type", "text/html");
  pipe(res);
});

Conditional Registration Pattern

// utils/setup.js
let registered = false;

function ensureRegistered() {
  if (!registered) {
    require("react-server-dom-webpack/node-register")();
    registered = true;
  }
}

module.exports = { ensureRegistered };

// Use in multiple entry points
const { ensureRegistered } = require("./utils/setup");
ensureRegistered();

Development vs Production Pattern

// server/setup.js
if (process.env.NODE_ENV === "development") {
  // Enable directive processing in development
  require("react-server-dom-webpack/node-register")();
}

// In production, components are pre-processed during build

Error Handling

The registration system provides comprehensive error handling for directive processing:

Conflicting Directives

// This will throw an error
"use client";
"use server"; // Cannot have both directives

// Error message:
// "Cannot have both 'use client' and 'use server' directives in the same file."

Parse Errors

// Malformed syntax in directive file
"use client";
export function Component() {
  // Syntax error here
  return <div>Hello</div>
}

// Error logged to console:
// "Error parsing [filename] [error message]"

ESM Loader Integration

For ESM modules, use the dedicated loader instead of the CommonJS register:

// package.json
{
  "type": "module",
  "scripts": {
    "dev": "node --loader react-server-dom-webpack/node-loader src/server.js"
  }
}

ESM Server Setup:

// server.js (ESM)
import { renderToPipeableStream } from "react-server-dom-webpack/server.node";
import App from "./components/App.js";

// ESM loader automatically processes directives
export function handleRequest(req, res) {
  const { pipe } = renderToPipeableStream(<App />, clientManifest);
  pipe(res);
}

Advanced Integration Patterns

Framework Integration

// next.config.js (example integration)
module.exports = {
  experimental: {
    serverComponentsExternalPackages: ["react-server-dom-webpack"]
  },
  webpack: (config, { isServer }) => {
    if (isServer) {
      // Ensure registration happens in server environment
      config.plugins.push({
        apply(compiler) {
          compiler.hooks.beforeRun.tap("RSCRegister", () => {
            require("react-server-dom-webpack/node-register")();
          });
        }
      });
    }
    return config;
  }
};

Testing Integration

// test/setup.js
const register = require("react-server-dom-webpack/node-register");

// Register before running tests
beforeAll(() => {
  register();
});

// test/server-components.test.js
const ServerComponent = require("../components/ServerComponent");

test("server component renders correctly", async () => {
  // ServerComponent contains "use server" directive
  const result = await ServerComponent.someAction();
  expect(result).toBeDefined();
});

Hot Reload Integration

// dev-server.js
const chokidar = require("chokidar");

// Watch for changes and re-register
chokidar.watch("./src/**/*.js").on("change", (path) => {
  // Clear module cache
  delete require.cache[require.resolve(path)];
  
  // Re-register to pick up directive changes
  require("react-server-dom-webpack/node-register")();
});

Performance Considerations

Module Caching

The registration system respects Node.js module caching:

// First import processes and caches the module
const Component1 = require("./MyComponent");

// Second import uses cached result
const Component2 = require("./MyComponent"); // Same instance

Directive Detection Optimization

The system performs fast string checks before parsing:

// Fast path: no parsing needed
if (content.indexOf('use client') === -1 && content.indexOf('use server') === -1) {
  return originalCompile.apply(this, arguments);
}

// Only parse files that might contain directives

Types

// No exported types - register() is a side-effect function
// The registration affects the module loading behavior globally

interface ModuleCompilerHook {
  /** Original Node.js module compilation function */
  _compile(content: string, filename: string): void;
}

interface DirectiveInfo {
  /** Whether file contains "use client" */
  useClient: boolean;
  /** Whether file contains "use server" */
  useServer: boolean;
  /** Parsed AST body for directive detection */
  body: any[];
}

Integration Notes

Build vs Runtime

  • Development: Use node-register for runtime directive processing
  • Production: Pre-process directives during build for better performance
  • Testing: Register hooks in test setup for consistent behavior

Compatibility

  • CommonJS: Use require("react-server-dom-webpack/node-register")()
  • ESM: Use --loader react-server-dom-webpack/node-loader
  • Mixed: Can use both in hybrid applications

Debugging

Enable verbose logging for directive processing:

// Set environment variable for debugging
process.env.DEBUG = "react-server-dom-webpack:*";

require("react-server-dom-webpack/node-register")();

Install with Tessl CLI

npx tessl i tessl/npm-react-server-dom-webpack

docs

client-apis.md

data-communication.md

index.md

nodejs-integration.md

server-apis.md

static-rendering.md

webpack-plugin.md

tile.json