19
Quick Tip - JavaScript Rendering
Originally Posted - https://aidangee.dev/blog/quick-tip-javascript-rendering
Minimal static HTML is served back to the user, this will most likely only contain links to scripts and CSS files. The JavaScript is in charge of generating the HTML in the browser.
Because there are no servers needed you will often see platforms that host static websites for free with a generous amount of network bandwidth e.g. Render, Firebase Hosting, Vercel, Netlify. Or you could run this yourself in AWS storing the files in S3 and backing with a CloudFront CDN for a very low cost (often a few cents a month).
Pros
Cons
Ideal for
HTML is generated at build time and the full static HTML will be served over the network to the user.
This generates static HTML files, which means much of the same low cost hosting solutions as the client side rendering example can be used. The difference being that with Static Generation you will have a HTML file per page generated, rather than just an index.html.
Pros
Cons
Ideal for
HTML is generated on request and the full static HTML will be served over the network to the user.
Pros
Cons
Ideal for
This can be considered a mixture of the above approaches. Frameworks like Next.js, Nuxt.js & SvelteKit (to name a few) have excellent APIs to achieve this.
To demonstrate this let us look at a simple example scenario with SvelteKit. Imagine we are building a blog with the following specification -
We could split these pages into different categories:
This sounds like it might be complicated to mix and match, but the frameworks make this easy.
Homepage (pages/index.svelte)
<script context="module">
// exporting this variable is all you need to do
export const prerender = true;
</script>
<svelte:head>
<title>Homepage</title>
<meta name="description" content="My homepage">
</svelte:head>
<main>
<!-- content goes here -->
</main>
Blog List (pages/blog/index.svelte)
<script context="module">
// export a load function to grab data server side
export async function load({ page, fetch, session, context }) {
const blogs = await fetch('https://mycms.io').then((response) => response.json());
return {
props: {
blogs
}
}
})
// we have static generation disabled
export const prerender = false;
</script>
<script>
export let blogs;
</script>
<main>
<BlogPosts blogs={blogs}/>
</main>
If you wanted to switch this to being statically generated like discussed above, you could just set prerender to true. (be aware, in svelte the load function is run on the client and server)
One more I wanted to include under the hybrid list is a feature of Nuxt.js and Next.js they call Incremental Static Regeneration (ISR). This can be viewed as a middle ground between SSR and SSG, if you use ISR then the page will be generated at build time like it would if you use static generation. But with ISR you specify a duration, and after this duration passed the page will be regenerated.

With this, you get the benefits of static generation but the increased frequency of updates that you get from SSR. This would actually be a good solution to our blogs list page from above. ISR can allow us to have a pre-rendered page but will update frequently enough to support any new blogs being added to the CMS.
Unfortunately, there is not one answer to how you should render your application. It is highly specific to what you are building. The good news is that hybrid rendering makes this specificity possible to allow best mix in your application.
For the best performance and low cost, static generation is recommended. I find myself saying 'can I pre-render this?' more and more, and often when I have something on the page that is dynamic like comments on a blog post. I'll mix in a component that grabs and renders that data client side before reaching for SSR. Why? This allows the initial content for the user to be pre-rendered with the dynamic part sprinkled on top in the client.
19