A Nuxt app can be rendered in various modes.
The default standard mode is simply called SSR. Specifically, it means Server-Side Rendering on request. “on request” means whenever the user clicks on an external link or enters a URL in the address bar to access a page.
The default mode is great for a highly-dynamic website with ever-changing content where timing is critical, such as news sites, forums, and e-commerce platforms.
However, there are other flavors of Server-Side Rendering that could be more suitable for your unique use cases:
- Static-Site Generation (SSG) is rendering each page only once at build time. This is great for websites that are content driven but they don’t get updates often, maybe only once a week, such as a documentation site. This is faster than the default SSG because the page doesn’t have to be generated on request. Additionally, you don’t need an app server for hosting an SSG site.
- Incremental Static Regeneration (ISR) is rendering that takes place in the background, and doing so from time to time to keep the content up-to-date. “In the background” means that it will serve the old version of the page while the new version is being generated in the background. And the new version will be served for future requests. This is great for content-driven websites that get updated often but the timing of the update is not critical as long as the sites do get updated within an hour or so, such as a blog. You can think of this as a mixture of the SSG and the default SSR. But it does require a hosting platform that supports CDN caching, such as Netlify and Vercel.
- SWR (Stale-While-Revalidate) is another mode that is similar to ISR, but it doesn’t require CDN cache, it can be cached with a regular app server. We’ll talk more about the difference between ISR and SWR in a bit.
While all of these modes are considered server-side rendering, they will also render the components on the client side. This behavior doesn’t change no matter what mode you’re using because Nuxt.js is fundamentally a Vue.js framework, and Vue.js is a Single-Page App framework. Regardless of what’s happening on the server, Single-Page App components have to render on the client side.
That’s also why Pure SPA Rendering is also an available mode in Nuxt.js. This will behave exactly the same as a standard Vue.js app without any Server-Side Rendering, but it will still be driven by the Nuxt.js file-based router. This is great for websites that don’t require SEO because you will not need an app server for hosting a pure SPA.
Aside from SEO, Server-Side Rendering in general is about gaining a performance edge on the first load of your site. So if both SEO and performance are not what you care about, it’s fine to just use Pure SPA Rendering.
Choose the right mode
To choose the right rendering mode for your project, you can use this set of questions as a reference:
So, for example, if SEO is important, if updates occur weekly or less often, if you want static hosting, and if first-load performance is important:
Your ideal choice would be SSG.
But there can be other project-specific factors that come into play, so you might still need a deeper analysis for your project before arriving to a decision.
Now that we know how to choose a rendering mode, let’s talk about how to configure it in the project.
Route Rules Configuration
By default, a Nuxt app will be rendered using the standard SSR, which generates the page on request. If we want something else, we can configure the rendering mode in the nuxt.config.ts file using the routeRules
property.
For instance, if you want SSG, use prerender: true
:
/nuxt.config.ts
export default defineNuxtConfig({routeRules: {'**': { prerender: true } // SSG},...
})
Double asterisk means all pages. We have to specify the pages because Nuxt.js allows us to render an app with different rendering modes for different pages. But for now, let’s render all the pages the same way.
And for ISR, we can set the isr
property with a number:
/nuxt.config.ts
export default defineNuxtConfig({routeRules: {'**': { isr: 300 }},...
})
This will now regenerate the pages on the first request 300 seconds after the previous regeneration. The regeneration process will occur in the background.
If you just want to host this on a regular app server, you can use swr
instead:
export default defineNuxtConfig({routeRules: {'**': { swr: 300 }},...
})
This will also regenerate 300 seconds after the previous regeneration.
And if you want to provide it with a first generation at build time, you can mix swr
and prerender
:
export default defineNuxtConfig({routeRules: {'**': { swr: 300, prerender: true }},...
})
Now the pages will be generated at build time, and then they will be regenerated in the background as the requests are hitting the server. And of course, you can also use isr
instead of swr
.
Next, let’s talk more about the differences between SWR and ISR.
SWR vs ISR
With a supported hosting platform, isr
will be cached in the CDN layer. So it will be faster than using swr
, which serves all the way from the original app server.
Furthermore, both isr
and swr
can be configured with a boolean instead of a number:
/nuxt.config.ts
export default defineNuxtConfig({routeRules: {'**': { swr: true }},...
})
This is where they become very different.
isr: true
will essentially function like an on-demand SSG, where the page will be rendered on demand, but it will not update again until you redeploy your website.
On the other hand, swr: true
will still regenerate the page with a new version in the background. The new version will replace the old version in the cache if they’re different.
Finally, if you do not want any type of Server-Side Rendering and prefer a pure Single Page Application (SPA), set ssr: false
.
export default defineNuxtConfig({routeRules: {'**': { ssr: false } // Pure SPA},...
})
Hybrid Rendering
Now let’s talk about Hybrid Rendering, that is, generating different pages with different modes.
You can specify the paths of the pages:
export default defineNuxtConfig({routeRules: {'/': { ssr: true }, // Home Page'/categories': { prerender: true }, // Categories Page'/categories/*': { swr: 300 }, // Category Pages'/posts/*': { swr: 60 } // Post Details Page},...
})
- The Home Page is generated on each request. Since SSR is the default behavior, this is optional.
- The Categories Page will be generated once at build time.
- The Category Pages will be also be regenerated in the background, so we use
swr: 300
. The asterisk means all pages within a directory. - The Post Details Pages will be regenerated incrementally.
Notice that we don’t refer to dynamic paths by their file names with their dynamic segments, such as /categories/[category] or /posts/[post]. We’re using the asterisk in place of the dynamic segment on the path.
Hybrid rendering is useful because not all pages share the same update frequency. For instance, the Home Page would need to be updated whenever one of the articles is updated. In contrast, the Categories Page would only need to be updated when a new article is added to the site.