performance-diagnosis · git:20260807.975fe85 · 2026-08-07 · sha256 0207074a3be57d25
performance-diagnosis git:20260807.975fe85A
Immutable. This exact content never changes and is served at /api/v1/blob/0207074a3be57d25.
---
name: performance-diagnosis
description: Diagnose and fix web-app performance across development, build, server, browser, and network paths. Use when investigating slowness, CPU spikes, loops, or bloat.
license: MIT
---
# Performance diagnosis
Measure the slow path before changing it. Inspect the framework and runtime first; use the Next.js patterns below when they match the project, and adapt the same evidence-first workflow elsewhere.
## Steps
### 1. Check for compile loops
```bash
ls -lh /tmp/*.log 2>/dev/null
# If any log is >100MB, a hot reload loop is running
```
Look for repeated module resolution errors in the dev server output. Common culprit: `geist/font/*` imports breaking with Turbopack. Fix by switching to `next/font/google`:
```ts
// layout.tsx — replace geist package imports
import { Geist, Geist_Mono } from "next/font/google";
const GeistSans = Geist({ subsets: ["latin"], variable: "--font-geist-sans" });
const GeistMono = Geist_Mono({ subsets: ["latin"], variable: "--font-geist-mono" });
```
### 2. Check file watching scope
If the project reads files outside its own directory at runtime:
```ts
// lib/something.ts
const ROOT = path.join(process.cwd(), ".."); // watches the parent dir
```
Turbopack watches any directory referenced by runtime file reads. Edits to files in `..` trigger full recompiles. Fix: scope reads to the project directory, or use `turbopack: {}` in `next.config.ts` to silence the warning while you plan a proper fix.
### 3. Check for uncached disk reads
```bash
grep -rn "fs.readFileSync\|fs.readdirSync" lib/ app/ src/ 2>/dev/null
```
Any function that reads files and is called from a server component runs on every request. Add a module-level cache:
```ts
let cache: ReturnType<typeof loadData> | null = null;
export function loadData() {
if (cache) return cache;
// ... read files ...
cache = result;
return cache;
}
```
### 4. Profile the bundle (production)
```bash
npx @next/bundle-analyzer
# or add to next.config.ts:
# bundleAnalyzer: { enabled: process.env.ANALYZE === 'true' }
```
Look for: large client components that could be server components, duplicate packages across chunks, packages that shouldn't be in the client bundle.
### 5. Find expensive server components
Server components re-render on every request in dev unless wrapped with `cache()`. Search for:
```bash
grep -rn "await fetch\|readFileSync\|prisma\.\|supabase\." app/ --include="*.tsx" --include="*.ts"
```
Any expensive call in a server component without `import { cache } from 'react'` wrapping it will run on every page load.
### 6. Report
State:
- Root cause (loop, file watching, uncached reads, bundle)
- Files changed and what changed
- Expected behavior after fix (idle CPU, hot reload time)