next-zonesv0.1.0

Zones on the Pages Router

A zone may use the App Router, the Pages Router, or both, like any Next.js app. A zone on the Pages Router is built, installed, swapped and rolled back like any other zone: in mode "zones" (live installs), in mode "single", with Next's output: "standalone", and in next-zones dev.

Its files#

docs/
  next.config.mjs          zoneConfig({ mount: "/docs" })
  pages/
    _app.tsx               the zone's own (optional)
    _document.tsx          the zone's own (optional)
    docs/
      index.tsx            /docs
      [slug].tsx           /docs/a, /docs/b…
  public/docs/…            served at /docs/…

How its pages are served#

Next never shows a Pages Router page and an App Router page in one document: going from one to the other loads a new document. So a Pages Router page renders whole in its own zone's build, as it would in that zone alone:

Live installs#

A new version of a Pages Router zone installs like any other. Its pages then render with the new build (its new build id); requests for the old version's data are answered 404, and Next's client reloads the page from the server.

To make open tabs follow at once, render <ZoneUpdates /> in the zone's _app:

// docs/pages/_app.tsx
import type { AppProps } from "next/app";
import { ZoneUpdates } from "@runsnip/next-zones/client";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <ZoneUpdates />
    </>
  );
}

After a swap, the tab's next navigation (a link, router.push, back or forward) loads a new document, which is the version just installed. Nothing reloads before the user navigates. Without it, a page the tab prefetched before the swap may show once more from the old version.

The static files of every version still in the store stay served, so a tab still on a replaced version keeps loading its chunks.

In the other modes#

Measured#

Sequential requests after a warm-up (tools/bench/latency.mjs, 3000 per path, 300 warm-up), Node 24.16, Apple M1, two alternating rounds (the two numbers), p50 in ms. The reference is the same pages in one app on next start with the same shell, whose proxy runs on every request in both:

Path Zones One app
getServerSideProps page 0.98, 1.07 0.85, 0.99
prerendered getStaticProps page 0.69, 0.65 0.58, 0.60
its /_next/data/… JSON 0.44, 0.45 0.43, 0.39

Zones' own code is about 5% of the busy time in a CPU profile (spikes/zones/RESULTS.md, "The Pages Router").

Edit this page on GitHub · Markdown