Next.js pages can feel sluggish not because the framework is slow, but because your CDN isn’t acting like a true edge network.
Here’s a Next.js app deployed on Vercel, serving a mix of static and SSR pages, with a focus on performance.
// pages/index.js
function HomePage({ data }) {
return (
<div>
<h1>Welcome!</h1>
<p>Server-rendered data: {data}</p>
</div>
);
}
export async function getServerSideProps() {
// Simulate fetching data
await new Promise(resolve => setTimeout(resolve, 100));
const data = "This was fetched on the server.";
return {
props: { data },
};
}
export default HomePage;
// pages/about.js
import fs from 'fs';
import path from 'path';
function AboutPage({ fileContent }) {
return (
<div>
<h1>About Us</h1>
<p>{fileContent}</p>
</div>
);
}
export async function getStaticProps() {
const filePath = path.join(process.cwd(), 'content', 'about.txt');
const fileContent = fs.readFileSync(filePath, 'utf-8');
return {
props: { fileContent },
};
}
export default AboutPage;
The Vercel CDN, when configured correctly, acts as a distributed network of edge functions. For static assets (like pages/about.js after getStaticProps runs), it means a file is served from the nearest data center to the user. For Server-Side Rendered (SSR) pages (pages/index.js with getServerSideProps), Vercel’s edge functions execute your Node.js code at the edge, not in a single origin server. This drastically reduces latency.
The core problem is understanding how Next.js’s rendering strategies map to Vercel’s edge capabilities. Static generation (getStaticProps) creates immutable files that are cached globally on the CDN. SSR (getServerSideProps) runs your code on Vercel’s edge functions, which are also distributed, but the output is dynamic and can be cached for short periods or not at all.
Consider the getServerSideProps example. When a user requests /, Vercel routes the request to an edge function closest to them. This function executes the getServerSideProps code, fetches the data, and returns the rendered HTML. The key is that this execution happens at the edge, not at a central origin server. If that same user hits the page again within Vercel’s default caching window for dynamic routes (typically 60 seconds), they’ll get a cached response from the edge. Subsequent requests from different users, even if they are geographically distant from the first, will also hit their nearest edge function.
The getStaticProps example is even more performant for static content. The about.txt file is read during the build process. The resulting HTML page is then uploaded to Vercel’s CDN and distributed to every edge location. When a user requests /about, the request is served directly from the nearest CDN edge server with no server-side computation required.
The system’s performance hinges on two main factors: Vercel’s global edge network and Next.js’s ability to leverage it through static generation and edge-function-powered SSR.
A common pitfall is assuming SSR always means a single origin server. Vercel’s architecture is designed to run SSR logic on its edge network. This is why even dynamic pages can feel fast.
The real power comes from intelligently choosing between getStaticProps and getServerSideProps. For content that doesn’t change per request, getStaticProps is king. For data that must be fetched on every request (e.g., user-specific data, real-time stock prices), getServerSideProps is necessary, but Vercel’s edge execution still offers a significant advantage over traditional server setups.
The one thing most people don’t realize is that Vercel’s edge functions for SSR can also be configured with specific cache TTLs, and these TTLs are applied per edge location. This means if you set a cache duration of 10 seconds, each edge location will independently cache the result for 10 seconds. It’s not a single global cache that invalidates for everyone; it’s a distributed caching mechanism that significantly reduces the chances of hitting an origin for repeated requests.
The next step in optimization involves exploring Incremental Static Regeneration (ISR) and Vercel’s revalidate prop in getStaticProps.