rwsdk
Version:
Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime
58 lines (57 loc) • 2.4 kB
JavaScript
import debug from "debug";
import fsp from "node:fs/promises";
import path from "node:path";
import { CLIENT_MANIFEST_RELATIVE_PATH } from "../lib/constants.mjs";
import { normalizeModulePath } from "../lib/normalizeModulePath.mjs";
const log = debug("rwsdk:vite:linker-plugin");
export function linkWorkerBundle({ code, manifestContent, projectRootDir, base, }) {
let newCode = code;
const manifest = JSON.parse(manifestContent);
// 1. Replace the manifest placeholder with the actual manifest content.
log("Injecting manifest into worker bundle");
newCode = newCode.replace(/['"]__RWSDK_MANIFEST_PLACEHOLDER__['"]/, manifestContent);
// 2. Replace asset placeholders with their final hashed paths.
log("Replacing asset placeholders in final worker bundle");
for (const [key, value] of Object.entries(manifest)) {
const normalizedKey = normalizeModulePath(key, projectRootDir, {
isViteStyle: false,
});
// If base is provided, prepend it with the final hashed path.
// Base is assumed to have a trailing "/".
const assetPath = (base ? base : "/") + value.file;
newCode = newCode.replaceAll(`rwsdk_asset:${normalizedKey}`, assetPath);
}
// 3. Deprefix any remaining placeholders that were not in the manifest.
// This handles public assets that don't go through the bundler.
log("Deprefixing remaining asset placeholders");
newCode = newCode.replaceAll("rwsdk_asset:", "");
return {
code: newCode,
map: null,
};
}
export const linkerPlugin = ({ projectRootDir, }) => {
let config;
return {
name: "rwsdk:linker",
configResolved(resolvedConfig) {
config = resolvedConfig;
},
async renderChunk(code) {
if (this.environment.name !== "worker" ||
process.env.RWSDK_BUILD_PASS !== "linker") {
return null;
}
log("Rendering final worker chunk");
const manifestContent = await fsp.readFile(path.resolve(projectRootDir, CLIENT_MANIFEST_RELATIVE_PATH), "utf-8");
const result = linkWorkerBundle({
code,
manifestContent,
projectRootDir,
base: config.base,
});
log("Final worker chunk rendered");
return result;
},
};
};