Files
WRNexusJS/packages/core/src/performance.ts
T
2026-08-01 10:04:42 +05:30

69 lines
1.9 KiB
TypeScript

export interface PerformanceBudgets {
routeJsBytes?: number;
routeCssBytes?: number;
htmlBytes?: number;
imageBytes?: number;
hydrationMs?: number;
serverRenderMs?: number;
/** Largest Contentful Paint in milliseconds. Recommended <= 2500. */
lcpMs?: number;
/** Interaction to Next Paint in milliseconds. Recommended <= 200. */
inpMs?: number;
/** Cumulative Layout Shift score. Recommended <= 0.1. */
cls?: number;
/** Time to First Byte in milliseconds. */
ttfbMs?: number;
/** Longest main-thread task in milliseconds. Recommended <= 50. */
longTaskMs?: number;
/** Number of client hydration boundaries on the route. */
hydratedComponents?: number;
/** Total request count for the initial navigation. */
requests?: number;
}
export interface PerformanceMeasurement {
routeJsBytes?: number;
routeCssBytes?: number;
htmlBytes?: number;
imageBytes?: number;
hydrationMs?: number;
serverRenderMs?: number;
lcpMs?: number;
inpMs?: number;
cls?: number;
ttfbMs?: number;
longTaskMs?: number;
hydratedComponents?: number;
requests?: number;
}
export interface BudgetViolation {
metric: keyof PerformanceBudgets;
budget: number;
actual: number;
overBy: number;
}
export const recommendedWebBudgets: Readonly<PerformanceBudgets> = Object.freeze({
lcpMs: 2500,
inpMs: 200,
cls: 0.1,
longTaskMs: 50,
routeJsBytes: 50 * 1024,
routeCssBytes: 25 * 1024,
});
export function checkPerformanceBudgets(
budgets: PerformanceBudgets,
measurement: PerformanceMeasurement,
): BudgetViolation[] {
const violations: BudgetViolation[] = [];
for (const metric of Object.keys(budgets) as Array<keyof PerformanceBudgets>) {
const budget = budgets[metric];
const actual = measurement[metric];
if (budget === undefined || actual === undefined || actual <= budget) continue;
violations.push({ metric, budget, actual, overBy: actual - budget });
}
return violations;
}