@wroud/vite-plugin-ssg
Version:
A Vite plugin for static site generation (SSG) with React. Renders React applications to static HTML for faster load times and improved SEO.
99 lines • 3.86 kB
JavaScript
import { fork } from "child_process";
import { fileURLToPath } from "url";
import { deserializeError } from "../utils/error/deserializeError.js";
export async function loadServerApi(module) {
let process = fork(fileURLToPath(import.meta.resolve("./run-server-api.js")), [module], {
stdio: "inherit", // This automatically forwards stdout/stderr to parent
});
let messageId = 0;
const activeListeners = new Set();
// Helper function to send message and wait for response
const sendMessageAndWaitForResponse = (type, instanceId, args) => {
return new Promise((resolve, reject) => {
const id = messageId++;
const onMessage = (response) => {
if (response.messageId !== id)
return;
process.removeListener("message", onMessage);
activeListeners.delete(onMessage);
if (response.success) {
resolve(response.data);
}
else {
reject(deserializeError(response.error));
}
};
activeListeners.add(onMessage);
process.on("message", onMessage);
process.send({
type,
instanceId,
messageId: id,
args,
});
});
};
return {
create: async (...args) => {
const instanceId = await sendMessageAndWaitForResponse("init", undefined, args);
return {
async render(htmlTags, timeout) {
return sendMessageAndWaitForResponse("render", instanceId, {
htmlTags,
timeout,
});
},
async getPathsToPrerender() {
return sendMessageAndWaitForResponse("getPathsToPrerender", instanceId);
},
async dispose() {
await sendMessageAndWaitForResponse("dispose", instanceId);
},
};
},
async dispose() {
if (!process) {
return;
}
try {
// First try to gracefully terminate by notifying the child process
await sendMessageAndWaitForResponse("dispose", undefined);
// Clean up any remaining listeners to prevent memory leaks
for (const listener of activeListeners) {
process.removeListener("message", listener);
}
activeListeners.clear();
// Check if the process is still running
if (process.connected) {
// Try SIGTERM first for graceful shutdown
process.kill("SIGTERM");
// Set a timeout to force kill if the process doesn't exit
await new Promise((resolve, reject) => setTimeout(() => {
try {
if (!process.killed) {
process.kill("SIGKILL");
}
}
catch (e) {
reject(e);
}
finally {
resolve(undefined);
}
}, 500));
}
}
catch (error) {
console.error("Error disposing server process:", error);
// Force kill as a last resort
if (process.connected && !process.killed) {
process.kill("SIGKILL");
}
}
finally {
process = null;
}
},
};
}
//# sourceMappingURL=loadServerApi.js.map