Learning Modern Next.JS (13) as a React Developer

Let me preface this post with a massive boulder of salt: although I have done a lot of React development, this was my first time using Next.JS and therefore there is a real chance I missed some things about Next.JS due to my inexperience.

You have been warned. 😁

Intro to Server-side Rendering and Next.JS

The concept of server-side rendering is surely familiar to any web developer that started before 2015 and likely most after as well even with the massive uptick in JavaScript-based alternatives.

Having used PHP and Apache for my first web project way back in 2014, I can also say that I was familiar with it. However, the way content was rendered back then with PHP was arguably more intuitive for a programmer since it mentally and literally translated to a few inline find and replaces. ("Back then" is not to say PHP is a thing of the past or anything it clearly still isn't).

Next.JS takes a different approach by pre-rendering React, which is predominantly used as a single-page framework.

The Next.JS Pipeline

  1. At build-time it splits the generated JavaScript into bundles by page and dependency tree to minimize load times.
  2. On request, Next.JS handles the first rendering of the HTML content by React.
  3. Pre-render is passed off to the client who is responsible for filling in the rest and enabling the usual interactivity (a.k.a, hydration).

How Next.JS effects the React workflow

The way Next.JS does its compilation and splitting can be left as a very mystical black box without having much of an effect on the programmer. However, the consequences of its approach to server-side rendering cannot be ignored.

Since React is both the server-side language and the client-side language, the client-side side-effects (say that 10 times fast) need to be woven into code that is also being run on the server-side, but ignored by Next.JS.

This was originally achieved by just using the useEffect hook, but as of Next.JS 13 with the app directory, components are explicitly declared as being client with the 'use client' literal directive at the start of the page. Arguably, the latter approach is more intuitive and relates back to the aforemented cut-and-paste mentality, but it still has some serious consequences for libraries that are not made for Next.JS 13.

Pain-points of Next.JS

This blog uses Chakra-UI which is not a Next.JS library. Although Chakra's maintainers have went to some lengths to facilitate their library's usage with Next.JS, it is not without some extra work by the developer.

For example, the new default server-side approach in Next.JS 13 encourages developers to cut their components into interactive and non-interactive chunks (components), and then label those interactive chunks to be client-side rendered.

But now using @chakra-ui/react often fails miserably in server-side components. And not necessarily in an easy-to-identify way:

Error: It's currently unsupported to use "export *" in a client boundary. Please use named exports instead.
Import trace for requested module:
./node_modules/@chakra-ui/react/dist/index.mjs
./app/layout.js

One solution is to wrap all Chakra components in a superficial 'use client' layer. See below.

'use client';

import { Text } from '@chakra-ui/react';

export default Text;

Recently the @chakra-ui/next-js package came out which is supposed to be bindings meant for Next.JS, but I have yet to be able to get it working on the blog without error. This is likely my fault for mixing elements from both packages.

Spamming 'use client'

Probably because of my failed attempts to get @chakra-ui/next-js working with the blog, I have found myself preferring to spam the 'use client' directive instead of creating wrapper components for Chakra-UI. Naturally, this is the worst possible solution to the problem...

... but it requires far less time.

Conclusion

While Next.JS provides an excellent way to use modern web libraries in a more efficient way, it does still require extra work (and extra knowledge) to get into.

So, if you're serious about the serious gains in performance Next.JS provides, it's worth taking a proper look into the nuances of Next.JS before doing what comes the easiest as a React developer... or you might regret it later. 😊