Skip to main content

Getting Started

Introduction

Boot performance is easy to break and hard to see. A single stray static import of a heavy SDK silently lands its whole module on the boot bundle:

  • import * as Sentry from '@sentry/nextjs' on a boot-reachable file adds real weight to Total Blocking Time (TBT), even if you only call init() later — deferring the call doesn't defer the parse.
  • A root-barrel import (e.g. @/components) can drag a validation library or an accessibility library onto a route that never needed it.
  • Replacing a dynamic import() with a static one removes a code-split boundary — the whole graph behind it lands on boot instead.

None of these throw an error. You find out from users, or a Lighthouse score that crept down over several unrelated PRs. And when you do measure, it's easy to draw the wrong conclusion: machine load can swing Total Blocking Time by 2× between two runs of the exact same build, and grepping a bundle for a package's import-path string false-positives on the very import('...') call sites that are already lazy.

@codeleap/perf exists to make this fast, repeatable, and honest — a CLI for React web projects (Next.js first, but the static analyzers work on any bundled output with a manifest) that:

You want to…CommandNeeds a server?
Know if a heavy library is on boot (seconds)boot-graphno
See which third-party packages the boot graph pullsimportsno
See chunk sizes and duplication of a configured library across chunkschunksno
Get real TBT/LCP/FCP, by floor rather than noisy medianmeasureyes
Explore boot CPU self-time by library (a secondary, exploratory signal)cpuyes
Run everything and get a PASS/FAIL verdict, e.g. for CIanalyzeoptional

It also bakes in the methodology that keeps the numbers trustworthy — SDK-internal markers instead of package-name substrings, comparison by floor instead of mean/median, and machine load recorded alongside every report — covered in Measuring Correctly.

Installing the Library

bun add -d @codeleap/perf

Then add a script:

{ "scripts": { "perf": "codeleap-perf analyze" } }

The codeleap-perf binary resolves from the installed package — no relative paths to a monorepo are required, so this works the same in a single-repo project as it does in a workspace.

Quick Start

# 1. Build the app — the static analyzers read the build output (Next.js: .next/)
bun run build

# 2a. Static-only — fast, no server, good for a pre-commit or CI-lint step
codeleap-perf analyze --no-server

# 2b. Full — start a prod server first, then measure too
bun run start &
codeleap-perf analyze

analyze always runs the static checks; it adds measure (and cpu, with --cpu) when a server is reachable, and exits with code 1 on a failing verdict so CI can gate a merge on it. That one command is enough for day-to-day use — the full breakdown of every command's output, every config field, and the programmatic API lives in the Reference.

Next steps

  • Command & Config Reference — every command's exact output, the full config field table, and the programmatic API's return types.
  • Measuring Correctly — the metrics, the methodology, and how not to fool yourself with a noisy machine.
  • Improving Boot Performance — a general playbook of changes that move TBT, and the comment-and-measure discipline used to validate each one.