vite-plugin-react-server
Version:
Vite plugin for React Server Components (RSC)
89 lines (88 loc) • 3.9 kB
JavaScript
import { createWorker } from "../worker/createWorker.js";
import { cleanupWorker } from "../helpers/workerCleanup.js";
import { serializedDevServerConfig } from "../helpers/serializeUserOptions.js";
import { MessageChannel } from "node:worker_threads";
import { React } from "../vendor/vendor.server.js";
import { getNodeEnv } from "../config/getNodeEnv.js";
import { handleError } from "../error/handleError.js";
import { envPrefixFromConfig } from "../config/envPrefixFromConfig.js";
import { setMaxListenersOnPort, unrefPort } from "../stream/setMaxListeners.js";
let currentWorker = null;
let isRestarting = false;
let currentHmrChannel = null;
export const restartWorker = async function _restartWorker({ server, autoDiscoveredFiles, userOptions, configEnv, hmrChannel, }) {
if (isRestarting) {
// Wait for the current restart to complete
while (isRestarting) {
await new Promise(resolve => setTimeout(resolve, 10));
}
return currentWorker;
}
isRestarting = true;
try {
// Terminate the current worker if it exists
cleanupWorker(currentWorker);
currentWorker = null;
// Clean up any existing HMR channel
if (currentHmrChannel) {
currentHmrChannel.port1.close();
currentHmrChannel.port2.close();
currentHmrChannel = null;
}
const routeCount = autoDiscoveredFiles.urlMap.size;
const hmrBuffer = 20; // Buffer for HMR and other operations
const maxListeners = routeCount + hmrBuffer;
// Create a new MessageChannel for this worker
const workerHmrChannel = new MessageChannel();
currentHmrChannel = workerHmrChannel;
// Increase max listeners to prevent warnings during development
setMaxListenersOnPort(workerHmrChannel.port1, maxListeners);
setMaxListenersOnPort(workerHmrChannel.port2, maxListeners);
unrefPort(workerHmrChannel.port1);
unrefPort(workerHmrChannel.port2);
// Forward messages from the plugin's HMR channel to the worker's channel
const messageHandler = (event) => {
workerHmrChannel.port1.postMessage(event.data);
};
hmrChannel.port1.addEventListener("message", messageHandler);
const workerResult = await createWorker({
projectRoot: server.config.root,
workerPath: userOptions.htmlWorkerPath,
reverseCondition: "react-client",
currentCondition: "react-server",
maxListeners: maxListeners,
envPrefix: envPrefixFromConfig(server.config),
workerData: {
userOptions: userOptions,
resolvedConfig: serializedDevServerConfig(server.config),
configEnv: configEnv,
reactVersion: React.version,
id: "worker/html",
serverManifest: {}, // staticManifest removed from AutoDiscoveredFiles
},
transferList: [workerHmrChannel.port2],
});
if (workerResult.type === "success") {
currentWorker = workerResult.worker;
if (userOptions.verbose)
server.config.logger.info(`[react-client] Set max listeners to ${maxListeners} for ${routeCount} routes`);
}
else if (workerResult.type === "error") {
const panicError = handleError({
error: workerResult.error,
logger: server.config.customLogger || server.config.logger,
mode: getNodeEnv(server.config.mode),
panicThreshold: userOptions.panicThreshold,
critical: false,
context: "restartWorker",
});
if (panicError != null) {
throw panicError;
}
}
}
finally {
isRestarting = false;
}
return currentWorker;
};