vercel/next.js
Lore
The story of how the Next.js codebase grew from a 438-commit toy project in late 2016 into the 33,000+ commit monorepo it is today. Dates are derived from git timestamps, tag dates, and the first appearance of major directories.
Eras
The first cut (Oct 2016 – Dec 2016)
The repository started on 5 October 2016 with the commit 04578072ec initial spec. Within a few months, Vercel (then ZEIT) had a working prototype: a Node server that rendered React pages out of a pages/ directory. By the end of 2016 there were 438 commits.
The early architecture was deliberately simple — a single server, file-system routing, and React's renderToString. This shape is still recognizable in packages/next/src/server/render.tsx today.
Maturing the Pages Router (2017 – 2019)
These years grew the framework's surface area: dynamic routes, custom App and Document, automatic static optimization, the next/link and next/image components, and getStaticProps / getServerSideProps data fetching.
Key milestones:
- Jul 2019 —
create-next-applands as its own package (packages/create-next-app/, first commit 2019-07-17). The CLI providesnpx create-next-appfor scaffolding new projects. - 2018-2019 —
next/imageand the image optimizer take shape inpackages/next/src/server/image-optimizer.ts. - 2019 —
next-serveris split out for serverless deployments.
Commit volume climbed from 1,290 in 2017 to 1,933 in 2019.
The Rust era begins (2020 – 2021)
Vercel hired the SWC author to build a Rust-based replacement for Babel. The integration arrives in late 2021:
- Nov 2021 —
packages/next-swc/is created (first commit 2021-11-21, "Extract next-swc Rust code into its own package"). This is the first Rust code in the repo. - The custom SWC transforms — for
next/font, the dynamic-IO plumbing, JSX import source tweaks — moved out of Babel into Rust, where they remain today incrates/next-custom-transforms/.
The Rust foothold makes future Turbopack integration possible.
App Router and React Server Components (2022 – Mar 2023)
The biggest single architectural shift in the framework's history. The App Router introduces React Server Components, streaming, server actions, and a new client router with prefetch and partial hydration.
- 2022 — Heavy work on RSC plumbing (commit volume jumps to 4,852 — nearly double 2021).
- Jan 2023 — A core file restructure ("Move core files to src folder and move JS files to TypeScript", PR #44405) consolidates the framework into
packages/next/src/. - Mar 2023 —
packages/next/src/server/app-render/lands (first commit6481c92038, 2023-03-15). The renderer that becomesapp-render.tsx(now ~7,000 lines) starts here. - App Router ships as stable in Next.js 13.4.
5,704 commits in 2023 made it the most active year so far.
Turbopack absorbs (Aug 2024)
The Turbopack bundler — built by the same Rust team — was developed as part of vercel/turborepo. In August 2024 the entire Turbopack subtree was merged into this repo:
- 2024-08-01 — Commit
becc655b0e Add 'turbopack/' from commit 'fb033c4917bb1bb98b238f1b4c7a928b66a90887'brought 54 Turbopack crates into the tree. - The next day, follow-up PRs (e.g.
7c3b279044 chore: fix references for the new turbopack crates) wired everything together.
After this, the turbopack/ directory and the existing crates/ directory cooperate: crates/next-core configures Turbopack for Next.js, and crates/next-api exposes the build to the JavaScript side via napi/wasm.
5,744 commits in 2024 — another record year.
Turbopack as default and cache components (2025 – 2026)
Turbopack moves from opt-in to the default for next dev, then for next build. The framework drops the --no-turbopack flag; webpack stays as --webpack.
The cache components feature — a unifying replacement for the previous Data Cache and Router Cache — lands behind __NEXT_CACHE_COMPONENTS=true. When enabled, most app-dir pages use Partial Prerendering (PPR) implicitly. Older ppr-full/ and ppr/ test suites are mostly describe.skip while the migration to cache components completes.
The latest tagged release at the time of this wiki is v16.3.0-canary.5, with v16.2.x as the most recent stable line.
Longest-standing features
| Feature | First introduced | Notes |
|---|---|---|
pages/ file-system routing |
Oct 2016 | Still active. The Pages Router is fully supported. |
next/link |
2016-2017 | Still the canonical client navigation primitive |
getServerSideProps |
2019 | Pages Router; complemented by Server Components |
next/image |
2020 | The image optimizer at server/image-optimizer.ts |
next/font |
2022 | Implementation in packages/font/ |
Major rewrites and migrations
| Migration | When | What changed |
|---|---|---|
| JavaScript → TypeScript core | Jan 2023 | PR #44405 moved core files to src/ and converted JS → TS |
| Babel → SWC for user code | 2021-2022 | SWC became the default compiler, Babel a fallback |
| webpack 4 → webpack 5 | 2020 | The major dependency bump; brought asset modules and persistent cache |
| Pages-only → App + Pages | 2022-2023 | Coexistence of two routers in the same app |
| Webpack → Turbopack as dev default | 2024 | After the subtree merge, Turbopack flipped to default for next dev |
| Webpack → Turbopack as build default | 2025 | next build defaults to Turbopack; --webpack is the opt-out |
Deprecated features
| Feature | Introduced | Deprecated | Replacement |
|---|---|---|---|
next export command |
Pre-2018 | 2023 | output: 'export' in next.config.js |
| AMP support | 2018 | gradually phased out | Native browser performance work |
next/legacy/image |
2020 | superseded by next/image (2022) |
Modern next/image with built-in priority |
| Custom server (advised) | 2017 | discouraged for App Router | Standalone output / adapter pattern |
Growth trajectory
xychart-beta horizontal
title "Commits per year"
x-axis ["2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025", "2026 YTD"]
y-axis "Commits" 0 --> 6000
bar [438, 1290, 1073, 1933, 2796, 2636, 4852, 5704, 5744, 5619, 1733]The doubling between 2021 (2,636) and 2022 (4,852) reflects both the App Router push and the Turbopack + SWC investments. Activity has plateaued since at ~5,500 commits/year as the project moves from new-feature density to stabilization and migration work.
Why is the App Router renderer so big?
packages/next/src/server/app-render/app-render.tsx is now ~7,000 lines. This appears to have happened because each new rendering capability — RSC, streaming, server actions, PPR, cache components, dynamic IO, instrumentation — landed as additions to the same render path rather than as separate pipelines. The render function deliberately interleaves RSC encoding, SSR, postpone-tracking, scheduling, and cache scoping so that all of these can interact within a single React render cycle.
Periodic refactors split out helpers (create-component-tree.tsx, walk-tree-with-flight-router-state.tsx, staged-rendering.ts) but the core function stays large because the React Server Components contract requires a single coordinated entry point.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.