React Server Components bindings for DOM using Webpack, enabling server-side rendering with streaming support and client-server communication.
—
Functions for encoding client-to-server data, decoding server responses, and handling form actions in React Server Components applications.
Encodes client-side data for transmission to the server, supporting complex data structures, files, and temporary references.
/**
* Encodes client data for server transmission
* @param value - Any serializable value to encode
* @param options - Optional encoding configuration
* @returns Promise resolving to encoded data in appropriate format
*/
function encodeReply(
value: ReactServerValue,
options?: EncodeReplyOptions
): Promise<string | URLSearchParams | FormData>;Usage Examples:
import { encodeReply } from "react-server-dom-webpack/client.browser";
// Encode simple data
const simpleData = await encodeReply({
action: "updateProfile",
userId: 123,
name: "John Doe"
});
// Encode with files
const formData = await encodeReply({
message: "Hello server",
files: [fileInput.files[0], fileInput.files[1]],
metadata: { timestamp: Date.now() }
});
// Encode with abort signal
const abortController = new AbortController();
const encodedData = await encodeReply(complexObject, {
signal: abortController.signal
});
// Send to server
await fetch("/api/server-action", {
method: "POST",
body: encodedData
});Decodes client-transmitted data on the server side, handling various formats including FormData and JSON strings.
/**
* Decodes client data sent to the server
* @param body - Request body containing encoded client data
* @param webpackMap - Optional server manifest for module resolution
* @param options - Optional configuration with temporary references
* @returns Promise resolving to decoded client data
*/
function decodeReply<T>(
body: string | FormData,
webpackMap?: ServerManifest,
options?: {temporaryReferences?: TemporaryReferenceSet}
): Thenable<T>;Usage Examples:
import { decodeReply } from "react-server-dom-webpack/server.node";
// Handle POST request with encoded data
export async function POST(request) {
const serverManifest = await loadServerManifest();
// Decode string body
const stringData = decodeReply(
await request.text(),
serverManifest
);
// Or decode FormData body
const formData = decodeReply(
await request.formData(),
serverManifest
);
// Process decoded data
const result = await processAction(formData);
return Response.json(result);
}
// Handle multipart uploads
async function handleUpload(request) {
const formData = await request.formData();
const decodedData = decodeReply(formData, serverManifest);
// Access files and regular data
const { files, userInput, metadata } = decodedData;
return processUpload(files, userInput, metadata);
}Specialized decoding for multipart form data using the busboy library, ideal for file uploads in Node.js environments.
/**
* Decodes multipart form data using busboy for Node.js
* @param busboyStream - Busboy stream processing multipart data
* @param bundlerConfig - Optional server manifest for module resolution
* @returns Promise resolving to decoded form data with files and fields
*/
function decodeReplyFromBusboy(
busboyStream: any,
bundlerConfig?: ServerManifest
): Promise<any>;Usage Examples:
import { decodeReplyFromBusboy } from "react-server-dom-webpack/server.node";
import busboy from "busboy";
import { IncomingMessage } from "http";
// Handle file upload with busboy
async function handleFileUpload(req: IncomingMessage) {
const bb = busboy({
headers: req.headers,
limits: { fileSize: 10 * 1024 * 1024 } // 10MB limit
});
const decodedData = await decodeReplyFromBusboy(bb, serverManifest);
// Process uploaded files and form fields
const { files, fields } = decodedData;
for (const file of files) {
console.log(`Uploaded: ${file.filename}, Size: ${file.size}`);
await saveFile(file);
}
return { success: true, uploadedFiles: files.length };
}
// Express.js integration
app.post("/upload", async (req, res) => {
try {
const result = await handleFileUpload(req);
res.json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
});Decodes form actions submitted from client components, returning executable server functions.
/**
* Decodes form action from client form submission
* @param body - FormData containing action information and arguments
* @param bundlerConfig - Optional server manifest for action resolution
* @returns Promise resolving to executable action function or null
*/
function decodeAction(
body: FormData,
bundlerConfig?: ServerManifest
): Promise<() => any> | null;Usage Examples:
import { decodeAction } from "react-server-dom-webpack/server.browser";
// Handle form action submission
export async function POST(request) {
const formData = await request.formData();
const action = await decodeAction(formData, serverManifest);
if (!action) {
return new Response("Invalid action", { status: 400 });
}
try {
// Execute the decoded action
const result = await action();
return Response.json(result);
} catch (error) {
return new Response(error.message, { status: 500 });
}
}
// Progressive enhancement form handling
async function handleFormSubmission(request) {
const formData = await request.formData();
// Try to decode as action first
const action = await decodeAction(formData, serverManifest);
if (action) {
// Handle as server action
return await action();
} else {
// Handle as traditional form submission
return handleTraditionalForm(formData);
}
}Decodes form state information for progressive enhancement and form validation scenarios.
/**
* Decodes form state from action result and form data
* @param actionResult - Result from previous action execution
* @param body - FormData containing current form state
* @param bundlerConfig - Optional server manifest for state resolution
* @returns Decoded form state for progressive enhancement
*/
function decodeFormState(
actionResult: any,
body: FormData,
bundlerConfig?: ServerManifest
): any;Usage Examples:
import { decodeFormState } from "react-server-dom-webpack/server.browser";
// Handle form with validation state
export async function handleFormWithState(request, previousResult) {
const formData = await request.formData();
const formState = decodeFormState(
previousResult,
formData,
serverManifest
);
// Use form state for validation and user feedback
if (formState.errors) {
return renderFormWithErrors(formState);
}
// Process valid form
return processValidForm(formState.data);
}
// Multi-step form handling
async function handleMultiStepForm(request, stepResult) {
const formData = await request.formData();
const currentState = decodeFormState(stepResult, formData, serverManifest);
if (currentState.isComplete) {
return processCompleteForm(currentState);
} else {
return renderNextStep(currentState);
}
}Common patterns for handling complex data structures in client-server communication.
Complex Object Encoding:
// Client-side: Encode complex nested object
const complexData = {
user: { id: 1, name: "Alice" },
preferences: { theme: "dark", notifications: true },
files: [file1, file2],
metadata: {
timestamp: new Date(),
location: navigator.geolocation
}
};
const encoded = await encodeReply(complexData);
// Server-side: Decode and access nested data
const decoded = decodeReply(await request.formData(), serverManifest);
console.log(decoded.user.name); // "Alice"
console.log(decoded.files.length); // 2File Upload Handling:
// Client-side: Encode files with metadata
const fileData = {
action: "uploadDocument",
files: Array.from(fileInput.files),
category: "documents",
tags: ["important", "project-a"]
};
const formData = await encodeReply(fileData);
// Server-side: Process uploaded files
const { action, files, category, tags } = decodeReply(formData, serverManifest);
for (const file of files) {
await saveFileWithMetadata(file, { category, tags });
}interface EncodeReplyOptions {
/** Set for tracking temporary references during encoding */
temporaryReferences?: TemporaryReferenceSet;
/** AbortSignal for cancelling encoding operation */
signal?: AbortSignal;
}
type ReactServerValue =
| string
| number
| boolean
| null
| undefined
| Array<ReactServerValue>
| { [key: string]: ReactServerValue }
| File
| Blob
| FormData
| URLSearchParams;
type ServerManifest = Record<string, any>;
type TemporaryReferenceSet = any;
interface DecodedFormData {
/** Uploaded files from multipart form */
files?: File[];
/** Form field values */
fields?: Record<string, string | string[]>;
/** Any additional encoded data */
[key: string]: any;
}Install with Tessl CLI
npx tessl i tessl/npm-react-server-dom-webpack