Gone are the days when you'd fetch data from your database, pass it to your view and render it. Well, these days aren't gone. But we can definitely do better.
Next.js has three different rendering modes: Server Side Rendering(SSR), Static Site Generation(SSR) and the newly minted ISR(Incrementation Site Regeneration). Each method serves a purpose and comes with its own pros and cons list -- let's get into those!
To illustrate how the three modes function, I've included a small amount of code you could use in a Next.js project.
The component makes a request for a list of public repos and, to introduce some variability, randomly selects the sort direction before rendering.
If you'd like to follow along, create a Next.js project(yarn create next-app) and replace the code found in pages/index.js.
SSG(Static Site Generation)
In the early days of the web, this is kinda how websites worked. HTML files were just stored on disc on a webserver and with each request these pages were served up. No trips to the database or rendering to be done, it's all ready to go and sitting there. Changing the page content is a bit of pain, but because everything is built and you're reading from disc, it's blazing-fast.
With SSG your pages are generated during Next.js' build step, and once these pages are created, that's it. They don't change until you run the build step again. This step is probably done as part of a CI/CD deployment process, so updating the site means running through that again before heading to production.
To try this out, yarn build and start your project. Once your site is ready, hit refresh a few times and you'll notice the order of the list never changes. That's because only 1 request for data was made and that happened at build time.
export default function Repos({ repos }) {
return (
<>
<h3>Repos</h3>
<dl>
{repos.map((repo, index) => (
<div key={index}>
<dt>{repo.name}</dt>
<dd>{repo.description}</dd>
</div>
))}
</dl>
</>
);
};
export async function getStaticProps() {
const direction = parseInt(Math.random() * 2) ? 'asc' : 'desc';
const res = await fetch(`https://api.github.com/users/vercel/repos?sort=created&direction=${direction}`, {
headers: {
'Accept': 'application/vnd.github.v3+json'
}
});
const repos = await res.json();
return {
props: {
repos
},
};
}
SSR(Server Side Rendering)
Pages are generated and returned after each page view. Think about how a traditional WordPress site works(also think about how slow WordPress can be). The slowness(lag) is introduced by way of network requests for data(DB & API calls etc.). The benefit being that as the content creator edits the page data in the CMS, those changes are reflected right away to the user.
Definitely a convenient way to manage your website, but your pages are going to be kinda slow to load.
Try building & running your project once again and notice how when you refresh(do it a few times) the sort order flips from ascending to descending. This is because with each refresh, the component is making a request to the API for data.
export default function Repos({ repos }) {
return (
<>
<h3>Repos</h3>
<dl>
{repos.map((repo, index) => (
<div key={index}>
<dt>{repo.name}</dt>
<dd>{repo.description}</dd>
</div>
))}
</dl>
</>
);
};
export async function getServerSideProps() {
const direction = parseInt(Math.random() * 2) ? 'asc' : 'desc';
const res = await fetch(`https://api.github.com/users/vercel/repos?sort=created&direction=${direction}`, {
headers: {
'Accept': 'application/vnd.github.v3+json'
}
});
const repos = await res.json();
return {
props: {
repos
},
};
}
ISR(Incrementation Site Regeneration)
For most, this is kind of the best of both worlds. ISR will create each page using SSR initially and store the response the same way SSG does. Subsequent requests for the same page will now be read from disc and be, you know, super-fast.
Content creators can make changes to their pages using a CMS and after the expiration period has lapsed, view their changes. What's really cool here is that Next.js is basically creating a caching layer for you. When it's time to regenerate the page, it'll do it behind the scenes and, once complete, replace the SSG page for future reads. Amazing stuff, really.
Because this version of code is only going to request new data every 10 seconds(validate: 10), I added a time stamp to the component. So once you've built and run it, refresh a few times and you'll notice that the time stamp doesn't change after the initial render. Refresh 10 seconds or so later and you'll see the time stamp change(and hopefully the sort direction).
export default function Repos({ repos, time }) {
return (
<>
<h3>Repos</h3>
<em>{time}</em>
<dl>
{repos.map((repo, index) => (
<div key={index}>
<dt>{repo.name}</dt>
<dd>{repo.description}</dd>
</div>
))}
</dl>
</>
);
};
export async function getStaticProps() {
const direction = parseInt(Math.random() * 2) ? 'asc' : 'desc';
const res = await fetch(`https://api.github.com/users/vercel/repos?sort=created&direction=${direction}`, {
headers: {
'Accept': 'application/vnd.github.v3+json'
}
});
const repos = await res.json();
const time = await new Date().toISOString();
return {
props: {
repos,
time
},
revalidate: 10
};
}
It's pretty easy to see why Next.js is so popular!
And if you’re having a hard time selecting the best rendering method, go for ISR :)
Thanks for reading.
Top comments (0)