May 7, 2025
In Next.js, "page data" refers to the JSON-serialized props and metadata tied to a page during Server-Side Rendering (SSR) or Static Site Generation (SSG). This is the data you return from getStaticProps, getServerSideProps, etc., which Next.js then serializes into JSON for client-side use.
In traditional Next.js applications (Pages Router, Next.js 12 and earlier), this page data is embedded in the HTML within a special <script> tag with the ID __NEXT_DATA__. If you're using SSG, it’s also saved as a .json file in the /_next/data/ directory.
In newer applications using the App Router (Next.js 13+), the process changes slightly: smaller script tags inject page data chunks by calling self.__next_f.push(), aiming for a more granular and efficient loading experience.
Because page data is parsed on the client, its size directly impacts performance. Ideally, your page data should be as lean as possible — just enough to render the first view.
Next.js will warn you if your page data exceeds 128 kB, a threshold chosen because larger payloads can noticeably delay hydration.
Before you optimize, you need to measure. Here's how you can inspect page data:
Pages Router:
To measure its size:
console.log('Page data size (kB):', new TextEncoder().encode(document.getElementById('__NEXT_DATA__').textContent).length / 1024);
App Router:
Download our service guide to understand how we can help you optimise your site speed
To estimate size, you can run:
console.log('Page data size (kB):', new TextEncoder().encode(JSON.stringify(window.__next_f)).length / 1024);
If your page data is bloated, here are some detailed strategies to reduce it:
This is the most critical rule. Carefully review what you return in getStaticProps and getServerSideProps. Only include the fields necessary for the first render. Avoid sending large, unnecessary objects, and especially avoid inlining large assets (like base64-encoded images or SVGs). If extra data is needed later, fetch it client-side after the page has hydrated.
If your page naturally wants to show a lot of data reconsider the UX. Perhaps implement pagination or infinite scroll, where getStaticProps only returns the first N items and subsequent items are fetched via an API route when the user scrolls. This way, initial page data stays small. Next.js supports dynamic routes and can generate pages for, say, /products/page/2. Alternatively, load additional chunks of data on the client side using a data fetching library (like SWR or React Query) after hydration.
Sometimes a large page data payload comes from a heavy component that isn't critical for the initial render. For example, an interactive graph.
In this case, dynamically import the component with ssr: false:
const Graph = dynamic(() => import('../components/Graph'), { ssr: false });
The initial page data shrinks, and the graph appears slightly after page load (you can show a spinner or placeholder). This technique essentially opts certain parts of the page out of SSR to keep the critical payload light. Use this with caution: only do it for non-critical or non-blocking parts of the UI, since you are trading some initial completeness for performance.
If you're using the App Router, React Server Components can be a game changer. Server Components fetch and render data directly on the server, meaning the data doesn't even touch the client as JSON. Instead, it gets embedded as HTML.
This approach reduces page payloads dramatically because there's no hydration required for server components — only client components (those using "use client") need serialized props.
Converting heavy data-driven parts of your page into Server Components helps you minimize reliance on __NEXT_DATA__ or self.__next_f.push, aligning with Next.js’s goal of reducing client-side JavaScript and improving Time to Interactive (TTI).
It’s worth noting that any data you do keep in page data is fully available to the client so make sure to never include any secrets. But for performance, think of page data as precious: every byte is delaying your user from seeing or interacting with the page. As one Next.js maintainer put it, only return the data that is needed to hydrate the page (first render) – any additional data can be loaded on client-side or on client transition.
Our experts in Next.js performance can help you improve the speed and performance of your app.Get in touchto learn how we can help.
Download our service guide to understand how
we can help you optimise your site speed