Optimization Plugins
Examine the optimization plugins that organize cache-stable chunk names, manage build skips, and generate manifest JSONs.
Key Files Location:
• Chunks Stabilizer:./dinou/esbuild/plugins-esbuild/stable-chunk-names-and-maps-plugin.mjs
• Skip Aborter:./dinou/esbuild/plugins-esbuild/skip-missing-entry-points-plugin.mjs
• manifest.json Writer:./dinou/esbuild/plugins-esbuild/manifest-generator-plugin.mjs
💡 Overview
In a dynamic React Server Component server, file names must remain stable across code edits during local runs to prevent browser cache invalidation and load failure crashes. Conversely, production releases require hashed manifests to prevent client-side CDN caching of outdated code.
📊 Stable Chunks Plugin Flow
The flowchart below traces the hash stripping and reference renaming steps of the stable chunk names plugin:
📊 Skip Missing Entries Flow
The flowchart below shows how compilation is aborted if a required entry file is missing:
📊 Manifest Generator Flow
The flowchart below shows how entrypoint names are mapped to final hashed filenames in the build manifest:
⚙️ stable-chunk-names-and-maps-plugin.mjs
Below is the full code of the stable chunk names resolver:
import path from "node:path";
export default function stableChunkNamesAndMapsPlugin({ dev = true } = {}) {
return {
name: "stable-chunk-names",
setup(build) {
build.onEnd(async (result) => {
if (!result.metafile || !result.outputFiles?.length) return;
const outdir = build.initialOptions.outdir;
if (!outdir) return;
const renames = new Map();
const normalizeRel = (p) => p.replace(/\\/g, "/");
// 1. Calculate stable names for chunks based on their source input path
for (const [oldRelPath, info] of Object.entries(result.metafile.outputs)) {
if (info.entryPoint || !oldRelPath.endsWith(".js")) continue;
const inputs = Object.keys(info.inputs);
const sourceFile = inputs.find((f) => f.startsWith("src/") && /\.(js|jsx|ts|tsx)$/.test(f));
if (!sourceFile) continue;
const rel = path.relative("src", sourceFile);
const normalizedRel = rel.replace(/\\/g, "/");
const dir = path.dirname(normalizedRel);
const base = path.basename(normalizedRel, path.extname(normalizedRel));
const stableName = dir === "." ? base : `${dir.replace(/\//g, "-")}-${base}`;
let finalName = dev ? `${stableName}.js` : `${stableName}-${oldRelPath.match(/-([A-Z0-9]+)\./)?.[1] || ""}.js`;
renames.set(path.basename(oldRelPath), `chunk-${finalName}`);
}
// 2. Rename associated sourcemaps
for (const [oldRelPath] of Object.entries(result.metafile.outputs)) {
if (!oldRelPath.endsWith(".js.map")) continue;
const jsLocal = path.basename(oldRelPath.replace(".map", ""));
if (renames.has(jsLocal)) {
renames.set(path.basename(oldRelPath), renames.get(jsLocal).replace(/\.js$/, ".js.map"));
}
}
// 3. Rewrite import statements inside JS chunks to match the new stable filenames
const outputs = result.metafile.outputs;
const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
for (const relPath in outputs) {
const output = outputs[relPath];
if (!output.imports || !relPath.endsWith(".js")) continue;
const importerFile = result.outputFiles.find((f) => normalizeRel(path.relative(process.cwd(), f.path)) === relPath);
if (!importerFile) continue;
let content = new TextDecoder().decode(importerFile.contents);
for (const imp of output.imports) {
const oldImportedLocal = path.basename(imp.path);
const newImportedLocal = renames.get(oldImportedLocal);
if (!newImportedLocal) continue;
const pattern = new RegExp(`"?\./${escapeRegExp(oldImportedLocal)}"?`, "g");
content = content.replace(pattern, `"./${newImportedLocal}"`);
}
importerFile.contents = new TextEncoder().encode(content);
}
// 4. Update sourceMappingURL annotations in JavaScript files
for (const file of result.outputFiles) {
if (!file.path.endsWith(".js")) continue;
const oldLocal = path.basename(normalizeRel(path.relative(process.cwd(), file.path)));
if (!renames.has(oldLocal)) continue;
const newLocal = renames.get(oldLocal);
const oldMapLocal = oldLocal.replace(/\.js$/, ".js.map");
const newMapLocal = newLocal.replace(/\.js$/, ".js.map");
let content = new TextDecoder().decode(file.contents);
content = content.replace(new RegExp(`sourceMappingURL=\./${escapeRegExp(oldMapLocal)}`, "g"), `sourceMappingURL=./${newMapLocal}`);
file.contents = new TextEncoder().encode(content);
}
// Apply updated paths to the build output object
for (const file of result.outputFiles) {
const oldLocal = path.basename(normalizeRel(path.relative(process.cwd(), file.path)));
const newLocal = renames.get(oldLocal);
if (newLocal) {
file.path = path.join(path.dirname(file.path), newLocal);
}
}
});
},
};
}⚙️ skip-missing-entry-points-plugin.mjs
Below is the full code of the skip missing entrypoints checker:
import { existsSync } from "node:fs";
export default function skipMissingEntryPointsPlugin() {
return {
name: "skip-missing-entry-points",
setup(build) {
// Intercept build initialization to perform files existence checks
build.onStart(async () => {
const entryPoints = build.initialOptions.entryPoints;
if (!entryPoints || typeof entryPoints === "string") return;
const missingEntries = [];
for (const [name, path] of Object.entries(entryPoints)) {
if (!existsSync(path)) {
missingEntries.push({ name, path });
}
}
// Halt compiler to avoid dumping fatal stack traces if a target component is missing
if (missingEntries.length > 0) {
return {
warnings: [{ text: "Missing entry points, skipping build. Neglect following error logs if any." }],
};
}
});
},
};
}⚙️ manifest-generator-plugin.mjs
Below is the full code of the output manifest generator:
import fs from "node:fs/promises";
import path from "node:path";
const frameworkEntryNames = ["main", "error", "serverFunctionProxy"];
export default function manifestGeneratorPlugin(manifestData) {
return {
name: "manifest-generator",
setup(build) {
const outdir = build.initialOptions.outdir || ".";
build.onEnd(async (result) => {
const meta = result.metafile;
if (!meta) return;
// Loop through entrypoints to extract framework script filenames
for (const [outputFile, info] of Object.entries(meta.outputs)) {
const entryPoint = info.entryPoint;
if (entryPoint) {
if (!/\.(js|jsx|ts|tsx|mjs)$/.test(entryPoint)) continue;
const entryName = outputFile.split("/").pop().split("-").shift();
if (!frameworkEntryNames.includes(entryName)) continue;
manifestData[entryName + ".js"] = outputFile.split("/").pop(); // Save filename mapping
}
}
try {
const outDir = path.resolve(process.cwd(), outdir);
await fs.mkdir(outDir, { recursive: true });
await fs.writeFile(path.join(outDir, "manifest.json"), JSON.stringify(manifestData, null, 2), "utf8");
} catch (e) {
console.error("Error writing manifest.json: ", e.message);
}
});
},
};
}