diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f4b463e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,48 @@ +# 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` |