Client performance budgets
npx warlock build reports each page’s first-visit JavaScript and CSS after
the Vite client build. Existing apps only receive a report until you configure
limits. New projects start with 150kb JavaScript and 50kb CSS limits.
import { defineConfig } from "@warlock.js/core";
export default defineConfig({ build: { budgets: { page: { js: "150kb", css: "50kb" }, pages: { "/admin/**": { js: "220kb" }, "/admin/reports": { js: "300kb", css: "75kb" }, }, mode: "error", }, },});Sizes accept b, kb, and mb (case insensitive), with 1024 bytes per kb.
Unspecified fields are unlimited; equality passes. page sets defaults.
pages keys match route paths: * stays within a segment, ** spans segments,
and ? matches one non-slash character. Later matching rules override earlier
fields while preserving other defaults. Other glob syntax is rejected.
Configured budgets default to mode: "error", which fails the build and
restores the previous dist. "warn" prints violations and completes normally.
Each violation names the page, JS or CSS budget, actual compressed size and
the largest contributing modules. API-only builds have an empty page report.
Inline payload budget
Section titled “Inline payload budget”build.budgets.payload limits the hydration data a single rendered document
embeds in its HTML: the page, layout and app data, translations, session, the
other hydration slots and the page’s browser route table.
export default defineConfig({ build: { budgets: { payload: { page: "64kb", pages: { "/admin/**": "128kb" }, mode: "warn", }, }, },});page is the limit for every document, and it defaults to 64kb. pages uses
the same route-path globs as the client budgets, and the later matching entry
sets the limit. mode is "warn" (the default) or "error". "warn" logs a
warning and "error" logs at error level; neither fails a request.
The measurement is a runtime one. A page’s payload depends on its loaders, which
only a request runs, so warlock build --json does not report it. Documents are
measured until their route is reported, once per process. When a route is over
budget, Warlock logs one line for that route with the size of
each section (page, layout, app, translations, routes, session, other) and the
three largest data keys. The check adds one serialization of the payload to
each document. Set page above what a healthy page embeds, or raise it for one
route, rather than turning the warning off.
The end-to-end kit records the same measurement for a loaded document with
page.measurePayload({ limit }) (see Browser end-to-end tests),
which adds it to the run’s evidence under payloads.
What is measured
Section titled “What is measured”The first visit includes hydration, the requested page, its layouts and root,
setup registration modules, and the error boundary. From those roots the report
walks the static imports and CSS references in Vite’s .vite/manifest.json.
Each emitted file is gzipped individually and counted once per page. Shared
chunks count toward every page that needs them. The report excludes HTML,
fonts, images, HTTP headers and cache reuse.
Dynamic imports beyond the required page roots and their static dependencies are reported in separate JS/CSS columns, including their transitive imports. They do not count against first-visit limits. This includes other pages exposed by the same hydration registry, so deferred totals describe reachable assets, not a prediction of what a user will download.
The ten largest modules use Rollup’s chunk.modules[].renderedLength, recorded
by a small build plugin. These are uncompressed rendered-byte estimates for JS
chunk contributors, including zero-length stylesheet wrapper modules. They are
diagnostic rankings rather than compressed per-module costs.
Deltas and machine-readable output
Section titled “Deltas and machine-readable output”The table sorts by combined JS and CSS size, descending, with route names
breaking ties. Deltas compare the same route and source path with the previous
successful build’s build-budgets.json in build.outdir (normally dist).
Keep that output directory between builds to retain the baseline. First builds
and new pages display no delta. Failed builds preserve the earlier baseline.
npx warlock build --json > build-report.jsonStdout contains one JSON object: { success, budgets, error? }; progress is
sent to stderr. budgets contains version: 1, compression: "gzip", pages
and violations. Each page records its route (page), source, byte totals
(js, css), dynamic totals, files, modules and optional delta.
Violations contain page, type, numeric budget and actual, and modules.
A budget failure returns a nonzero exit status while still printing the attempted
report; an earlier build failure may have no budgets value.
The full module attribution is private build metadata in
client/.vite/budget-modules.json. Production asset routes do not expose that
folder. No extra dependency is required.