Open-Source Wikis

/

Next.js

/

Lore

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 2019create-next-app lands as its own package (packages/create-next-app/, first commit 2019-07-17). The CLI provides npx create-next-app for scaffolding new projects.
  • 2018-2019next/image and the image optimizer take shape in packages/next/src/server/image-optimizer.ts.
  • 2019next-server is 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 2021packages/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 in crates/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 2023packages/next/src/server/app-render/ lands (first commit 6481c92038, 2023-03-15). The renderer that becomes app-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.

Lore – Next.js wiki | Factory