# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Commands ```bash npm run build # compile TypeScript → dist/ npm run dev # watch mode (tsc --watch) ``` No test runner is configured. ## Architecture An rspack plugin that intercepts browser requests during compilation and serves a progress page instead of the real app. ### Data flow ``` Compiler hooks → BuildState → Middleware → Browser (polling) ``` **`src/state.ts`** — plain mutable object (`BuildState`) shared between the plugin and middleware within the same Node.js process. Instance-scoped (created per `apply()` call) to support multi-compiler configs. **`src/plugin.ts`** — the plugin class. `apply(compiler)` does three things: 1. Registers `compiler.webpack.ProgressPlugin` to update `buildState.percentage`, `buildState.message`, `buildState.moduleName` (rspack passes `...items: string[]` spread from Rust; `items[0]` is either a file path or a phase label like `"finish make"`) 2. Taps `watchRun` / `invalid` / `done` to set `isBuilding` flag. `done` uses `tapPromise` to support the `delay` option 3. Wraps `compiler.options.devServer.setupMiddlewares` inside `afterEnvironment` hook — this is how middleware is injected with zero user config changes **`src/middleware.ts`** — intercepts requests while `isBuilding=true`. Serves the HTML wait page only for `Accept: text/html` requests (skips JS/CSS/etc). Exposes `GET /rspack-wait-page/progress` as a JSON polling endpoint. `PROGRESS_ENDPOINT` is exported so `template.ts` can reference it without a hardcoded string. **`src/template.ts`** — pure function returning a self-contained HTML string. Server-renders current progress on first load; a polling script takes over from there. `formatDetail()` handles both module paths (shortened to last 2 segments) and phase labels (shown as-is). ### Key rspack behaviour - `ProgressPlugin` callback receives `(percentage: number, msg: string, ...items: string[])` where rspack spreads `items[]` from Rust — only one item is passed in practice - `afterEnvironment` fires after user config is applied but before dev server starts, making it the correct hook for mutating `devServer.setupMiddlewares` - `done.tapPromise` (not `tap`) is required to hold `isBuilding=true` during the `delay` option window ### Plugin options | Option | Default | Purpose | |---|---|---| | `title` | `"Building…"` | Browser tab title | | `disableAfterFirstBuild` | `true` | Stop intercepting after first successful build | | `delay` | `0` | Artificial hold (ms) after build finishes, for testing the wait page | | `pollInterval` | `100` | Browser polling interval (ms); error back-off is `pollInterval * 5` |