-
Notifications
You must be signed in to change notification settings - Fork 210
Description
Problem
index.ts (3,528 lines) and app-dev-server.ts (2,734 lines) are the two largest files in the codebase. Both files mix Vite plugin logic with massive template string blocks that generate runtime JavaScript modules. This creates several problems:
- AI agents can't hold the entire file in context. These files exceed typical context windows, leading to partial reads and missed interactions between sections.
- Template string edits are error-prone. The generated code uses escaped characters (
\\n,\\.),varinstead ofconst/let, and mixes interpolated expressions with static code. AI agents routinely break escaping or confuse plugin code with generated runtime code. - No way to test generated code in isolation. The template strings are embedded in plugin functions, so the only way to verify generated output is to run the full dev/build pipeline.
What needs to be extracted
From index.ts
| Template | Lines | Span | Function | Generates |
|---|---|---|---|---|
| Pages Router prod server entry | 806-1549 | ~743 lines | generateServerEntry() |
Complete production server module: SSR, ISR, API routes, i18n, asset injection, middleware, route matching |
| Middleware runtime | 655-801 | ~147 lines | middlewareExportCode variable |
Middleware matching and execution, ReDoS protection (embedded inside the server entry) |
| Pages Router client entry | 1576-1634 | ~58 lines | generateClientEntry() |
Client hydration: page loaders, _app wrapping, hydrateRoot() |
The server entry template (743 lines) is the primary target. It contains the entire Pages Router production request lifecycle as a template string.
From app-dev-server.ts
| Template | Lines | Span | Function | Generates |
|---|---|---|---|---|
| RSC entry | 201-2060 | ~1,860 lines | generateRscEntry() |
The entire App Router request handler: route matching, middleware, CSRF, config redirects/rewrites/headers, metadata routes, server actions, layout tree construction, RSC streaming, caching |
| SSR entry | 2070-2425 | ~356 lines | generateSsrEntry() |
RSC-to-HTML rendering, progressive streaming, font/head injection |
| Browser entry | 2436-2733 | ~298 lines | generateBrowserEntry() |
Client hydration, RSC navigation, server actions, prefetch cache, HMR |
The RSC entry template (1,860 lines) is the largest single template string in the codebase. It contains at least 15 logically distinct subsystems inlined as generated code.
Proposed approach
1. Create an entries/ directory
packages/vinext/src/entries/
pages-server-entry.ts # From index.ts generateServerEntry()
pages-client-entry.ts # From index.ts generateClientEntry()
app-rsc-entry.ts # From app-dev-server.ts generateRscEntry()
app-ssr-entry.ts # From app-dev-server.ts generateSsrEntry()
app-browser-entry.ts # From app-dev-server.ts generateBrowserEntry()
Each file exports a function that takes the same parameters the current generator functions receive (route table, config, feature flags) and returns the generated code string.
2. Add snapshot tests
For each extracted template function, add a test that:
- Calls the function with representative inputs (a few routes, middleware present/absent, basePath set/unset, i18n enabled/disabled)
- Snapshots the generated output
- When an AI edits a template, the snapshot diff shows exactly what changed in the generated code
This is the key safety improvement. Currently there's no way to see what the generated code looks like without running the full pipeline.
3. Reduce index.ts and app-dev-server.ts to orchestration
After extraction, index.ts should be the Vite plugin shell (resolveId, load, configureServer, config hooks) that calls into the entry generators. app-dev-server.ts should be a thin module that calls the three App Router entry generators.
Non-goals
- Don't eliminate the template string pattern entirely. Code generation via template strings is the right approach for virtual modules that need dynamic imports based on the scanned route table. The goal is to isolate the templates, not replace them.
- Don't refactor the generated code's internal logic. That's a separate concern (see the shared request handler issue). This issue is purely about file organization.
Verification
pnpm test(all Vitest tests pass)pnpm run test:e2e(all Playwright E2E tests pass)pnpm run typecheckpnpm run lint- Manually verify that
index.tsis under 1,000 lines andapp-dev-server.tsis under 500 lines after extraction