47 lines
2.0 KiB
TypeScript
47 lines
2.0 KiB
TypeScript
const NODE_MODULES_SEGMENT = "/node_modules/";
|
|
|
|
const CHUNK_MATCHERS: Array<{ chunkName: string; packages: string[] }> = [
|
|
{ chunkName: "vendor-react", packages: ["react", "react-dom", "react-router", "scheduler", "use-sync-external-store"] },
|
|
{ chunkName: "vendor-core-utils", packages: ["clsx", "tailwind-merge", "class-variance-authority"] },
|
|
{ chunkName: "vendor-charts", packages: ["recharts", "victory-vendor", "d3-", "d3"] },
|
|
{ chunkName: "vendor-markdown", packages: ["marked", "katex"] },
|
|
{ chunkName: "vendor-monaco", packages: ["@monaco-editor/react", "monaco-editor"] },
|
|
{ chunkName: "vendor-editor-tiptap", packages: ["@tiptap/"] },
|
|
{ chunkName: "vendor-editor-prosemirror", packages: ["prosemirror-"] },
|
|
{ chunkName: "vendor-pdf", packages: ["@react-pdf/renderer"] },
|
|
{ chunkName: "vendor-workflow", packages: ["@xyflow/react"] },
|
|
{ chunkName: "vendor-aws-sdk", packages: ["@aws-sdk/", "@smithy/"] },
|
|
// Lighthouse-CI (#70) — splits the React-Email render path off the
|
|
// critical render bundle so transactional-email pages don't bloat the
|
|
// marketing TTI score. Matches the budget declared in scripts/bundle-budgets.json.
|
|
{ chunkName: "vendor-react-email", packages: ["@react-email/", "react-email"] },
|
|
];
|
|
|
|
const normalizeModuleId = (id: string) => id.replace(/\\/g, "/");
|
|
|
|
const hasPackageBoundary = (moduleId: string, packageName: string) => {
|
|
const packageRoot = `node_modules/${packageName}`;
|
|
|
|
if (packageName.endsWith("/") || packageName.endsWith("-")) {
|
|
return moduleId.includes(packageRoot);
|
|
}
|
|
|
|
return moduleId.includes(`${packageRoot}/`) || moduleId.endsWith(packageRoot);
|
|
};
|
|
|
|
export function getManualChunkName(id: string): string | undefined {
|
|
const normalizedId = normalizeModuleId(id);
|
|
|
|
if (!normalizedId.includes(NODE_MODULES_SEGMENT)) {
|
|
return undefined;
|
|
}
|
|
|
|
for (const matcher of CHUNK_MATCHERS) {
|
|
if (matcher.packages.some((packageName) => hasPackageBoundary(normalizedId, packageName))) {
|
|
return matcher.chunkName;
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
}
|