../

The 0kb Next.js blog

Update 3rd April 2023

This blog post applies to pages dir - which is the majority of Next.js apps. I cannot confirm if this will still work on the upcoming app dir, in Next 13.

Ok so this was a little bit clickbaity, but it's not technically a lie. This entire website has zero JavaScript on every single page... a Next.js app with zero client side JS. How can this be possible?

Context

Next.js is a huge abstraction of ReactDOMServer and other helpful utilities for building server side rendered apps powered by React. It's really easy to get started with, and features things like file system routing, statically generated content and much much more. I'm not trying to advertise it but I really really love it. There are a couple things to take in from the first sentence here, server side rendering and React.

For those of you who are not familiar with React, it's a JavaScript framework for building user interfaces. It handles the view layer of an app and is used to render the UI. Next.js takes this a step further and allows you to write your own view layer to have the first render performed on a server, which allows for a lot of performance and UI optimizations because we can ship back a lot less to the client (foreshadowing).

Runtime JS

With something called the Next.js PageConfig, we can instruct Next.js to supply zero runtime JS to the client. It comes with a couple trade offs but the general idea is that we perform our first render on the server (executing JavaScript) and the resulting HTML and CSS is "frozen" and sent down to the client over the wire. Zero JavaScript runtime in the browser, no <script> tags in sight!

Why not...?

As the saying goes, there's no such thing as free lunch. As with anything, doing this comes with some tradeoffs. For example, Next has a lot of built in React components that can speed up not only your app, but also development speed. Using the zero kb mode, we unfortunately cannot make full use of the next/link component; a component that prefetches pages so that clicks on links don't cause a full page reload. Additionally, we cannot use next/image as this also requires some minimal runtime JavaScript (a regular img works just fine). This also means zero state updates or literally any JavaScript that would've otherwise been bundled can run.

However, apart from that, we are able to eliminate all JavaScript completely. No more worrying about installing momentjs and watching your user count drop in realtime. See your gorgeous website in pure static HTML & CSS. Gone are the days of bundlephobia.com... I bet at this point you are itching to know how to enable it. Well, here's a quick example:

import {PageConfig} from 'next';

export const config: PageConfig = {
	unstable_runtimeJS: false,
};

export default function IndexPage() {
	return <h1>This page has no JavaScript!</h1>;
}

And boom! just like that, 0kb bundle. If you are going to use this though, just bear in mind that as well as the trade offs mentioned above, you literally cannot use any JavaScript in the client anymore for this page. Zero. Nada. Null. Void. That means no state updates, no SWR requests. No useEffects (thank god tbh).

p.s please check out my twitter @alistaiir :)