Rendering Strategies in Next.js


We talked about Request Memoization (put the link here) in the last blog. I want to talk about the various rendering strategies that Next.js provides.
Before that, there’s something that you would want to know which is that Next.js renders pages and caches them in something called Full Route Cache
by default. This ensures better SEO, and faster delivery of content through Content Delivery Networks, CDNs. We will talk about the Full Route Cache
in a bit, but first let’s discuss about the rendering strategies.
Please note that this blog talks about these strategies in the context of App Router
. Opting into such strategies may differ if you prefer Pages Router
. In such a case, I would suggest you to scan the through the official Next.js documentation for more information.
There are three kinds of rendering strategies:
Static Site Generation or SSG
All routes that opt into SSG as rendering strategy are rendered on the server during build time and are cached.
These routes are served directly from the cache whenever they are cached and if any change occurs to the content that these routes host, those will be reflected in the next build or deployment.
This is the default rendering strategy in Next.js’s App Router.
One can opt into by ensuring a few things:
There should not be usage of any unique dynamic APIs in the route for e.g. cookies, headers, params, etc.
Declaring
export const dynamic = 'force-static'
at the top of the rootPage.js
file. (not mandatory. A page will be by default considered static if it satisfies the condition needed for a page to be statically rendered.)Ensuring usage of static safe APIs with cache options on the fetch API set to
cache: 'force-cache'
This kind of rendering strategy is best used for web pages that are not dynamic. For e.g. blogs, documentations, product description, etc.
Incremental Static Regeneration or ISR
This kind of rendering strategy can be thought of as an upgrade to SSG.
Routes that opt into this rendering strategy are rendered on the server during build time for the first time, and then based on re-validation time, or manual invalidation of the cache, the routes are invalidated and re-rendered on the server to return the updated content hosted on these webpages.
- So, as long as the cache is not invalidate, the web pages are server from the cache. Once invalidated, the web pages are rendered again on the server, and the old cache content is replaced with the brand new rendered web page from the server for subsequent requests.
One can opt into this rendering strategy by ensuring a few things:
- Either Set the
revalidation
property at the top of thePage.js
file to a valuegreater than 0
.
- Either Set the
export const revalidation = 2500;
export const function Page() {
return <>
//JSX
</>
};
ii. or, set the next.revalidate
property in the fetch API options to a value greater than 0
const response = await fetch(url, { next: { revalidate: 2500 } });
(The above two ways are part of the strategy called on time revalidation
)
iii. Or, one can even set tags on fetch APIs such that revalidation can be done using revalidate
method and providing this method with the tag of the API that needs to be revalidated.
const response = await fetch (url, { next: { tags: ['a'] }});
Server Side Rendering or SSR
This kind of rendering strategy is really great for sections of the website that are highly dynamic and can be generated on demand.
Pages are rendered on demand every time a client requests for a web page to the server.
This kind of rendering strategy never makes use of
Full Route Cache
on the server, as the web page is dynamic in nature and has to be rendered on the server every time a request is sent to the server for it.One can opt into the kind of rendering strategy by ensuring a few things:
Either set
export const dynamic = 'force-dynamic'
at the top of thePage.js
file. (not mandatory because if the page already contains dynamic APIs, Next.js will consider it to be a dynamically rendered page)or set
revalidate
to0
at the top ofpage.js
file.
export const revalidate = 0;
export default function Page () {
return <>
// JSX
</>
}
c. or set cache: 'no-store'
in fetch API options.
const response = await fetch (url, { cache: 'no-store' });
d. or set next.revalidate
in fetch API options to 0
const response = await fetch (url, { next: { revalidate: 0 }});
e. or use dynamic APIs in the page such as cookies
, headers
, params
, etc.
Well, that’s it for this blog. Next we will discuss about how pages are rendered on the server and look into the usage of generateStaticParams
and how streaming works.
Subscribe to my newsletter
Read articles from Nikhil Kumar Patra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Nikhil Kumar Patra
Nikhil Kumar Patra
Web Development fanatic, excited about learning anything related to the same, from the basics to the advanced. I am a final year undergraduate at the International Institute of Information Technology, Bhubaneswar. I like to solve problems and learn about complex algorithms, and new technologies, and I aspire to create an impact in the world of Computer Science someday ❤️. Apart from Web Development, I am currently exploring and learning about iOS App development.