April 25, 2021 | Issue #4 | Twitter logoShare

Next.js + TypeScript, the Big List of Tools, and Upcoming Features πŸ§˜β€β™‚οΈ

😌 Wadup Next.js devs, time flew since the last issue. Here's why: I was working heavily on my SaaS (TurnShift, 100% Next.js). This time we'll talk about TypeScript. Whether you already use it or not with Next.js, I think you might learn something new.

If You're Not Using TypeScript, You're Missing Out.

The TypeScript logo

(And if you're already using it, keep on reading).

That's a bold statement.

I never bought a DVD nor blu ray player. I always thought I was fine streaming or downloading movies from the Internet. When legal streaming became popular, I thought: "Good thing I never bought those things.". Since then, I've always used this story to choose if I should try a technology or not. Is the investment (time, money) worth it? Is this technology here for the long run? Does it bring enough value compared to what I am using right now?

When CoffeeScript came out, I was skeptical: should I follow the trend and write all my code with it? Dropbox did in 2012. But the world of JavaScript developers never fully embraced CoffeeScript and, instead, JavaScript applied ideas from CoffeeScript (arrow functions for example).

When TypeScript came out I thought: I'll wait for its ideas to come to JavaScript. But more and more I feel I am missing out: a lot of projects I use and love are written in TypeScript (Next.js codebase, Stripe API client, Slack API client…). In December 2020, I decided I would give it another try, and this time it worked. In 2017, Dropbox rewrote everything in TypeScript.

If you need a single argument for TypeScript, here it is: it provides a developer experience that JavaScript cannot provide alone. In JavaScript, with the correct code editor, you get autocompletion on objects you instantiate, like:

import ApiClient from "somelib";

const apiClient = new ApiClient();
// apiClient.* => Code editor will autocomplete here, good :)

But a lot of my code looks like this:

someUtilityFunction(apiClient);

function someUtilityFunction(apiClient) {
  // apiClient.* No more autocompletion
  // Code editor: "I don't know what apiClient is, sorry."
}

And finally, here's a very frequent frustrating JavaScript developer experience:

export default apiHandler(req, res) {
  // req.*??? What even is `req`?
  // Code editor: "I don't know mate, but good luck!"
}

Here's a list of features I enjoy about TypeScript I did not know existed before I tried it:

  1. Autocompletion and type checking everywhere: In JavaScript, you get autocompletion only on objects you instantiate yourself. In TypeScript, on everything you provide a type for (this topic will become very clear in the example code).
  2. Backend and frontend types sharing: Define types in the backend, get properties autocompletion on the frontend.
  3. Whole-codebase refactors: once your codebase is typed, you can rename the name property of user to firstName with a single action, backend AND frontend. No more error-prone search and replace in many files (user/currentUser/..).
  4. No more PropTypes. You automatically get hints on missing (required) and extraneous props given to components, without having to use PropTypes.

Here's How to Write Next.js Code with TypeScript

The TypeScript Next.js documentation

First, you'll want to setup a TypeScript environment with Next.js, follow the official documentation. If you're dealing with an existing codebase, do not rename all files to .ts and .tsx. My codebase right now is a mix of .js, .jsx, .ts, .tsx files and it works perfectly well. I just made it a rule to:

  1. write every new code in TypeScript
  2. When modifying an existing JavaScript file, upgrade it into a TypeScript one.

If you never wrote TypeScript, you can't just scan those lines. You'll have to read them.

We start with an API route:

// pages/api/user.ts

// We import Next.js types to use them and get autocompletion on request
// and response helpers for example, without having to look at the
// documentation so often
import { NextApiRequest, NextApiResponse } from "next";

// We create our user type and export it right away,
// so we can use it on the frontend πŸͺ„
export type User = {
  name: string;
  age: nubmer;
  email: string;
};

export default async function userApi(
  req: NextApiRequest,
  // We expect the response of the api route to always be a User.
  // This is useful to make sure you're being consistent backend/frontend,
  // no more guessing properties
  res: NextApiResponse<User>,
): Promise<void> {
  // most probably you would get the user from your database here
  const user: User = {
    name: "Vincent",
    age: 36,
    email: "vincent@codeagain.com",
  };

  res.status(200).json(user);
}

And a Next.js page calling this route:

// pages/User.tsx

// https://nextjs.org/docs/advanced-features/module-path-aliases
import type { User } from "pages/api/User";

export default function UserPage(): JSX.Element {
  const [user, setUser] = useState(null);

  // most probably you would get your user by using:
  // - SWR: https://swr.now.sh
  // - React Query: https://react-query.tanstack.com
  // - useEffect + fetch:
  // https://reactjs.org/docs/testing-recipes.html#data-fetching
  useEffect(function () {
    const user: User = await fetch("/api/user").then((res) => res.json());
    setUser(user);
  }, []);

  if (user === null) {
    return "loading...";
  }

  return (
    <div>
      {user.name} is {user.age} old, send them an email at {user.email}.
    </div>
  );
}

That's pretty much all I use from TypeScript in my Next.js code. I had to fight with a few topics like making TypeScript happy about import Icon form "svg/icon.svg" or some ORM stuff but nothing serious.

I found the React TypeScript Cheatsheets to be very helpful while learning how to write tsx files.

Good luck! πŸ€

PS: If you own or owned a DVD/blu ray player, that's fine. I was just cheap.

Tools and Plugins πŸ”­

Next.js API Middleware β€” This library attempts to provide minimal, clean, composable middleware patterns that are both productive and pleasant to use. Kind of like next-connnect but with different API choices that could fit your preferences.

NextStripe β€” Simplified server-side Stripe workflows in Next.js. I've had to implement Stripe for my SaaS too, and if I had to do it again, I would try this library.

πŸ₯€Β The big list of tools:

Here's a list I curated of recent, popular, and well maintained Next.js packages I recommend.

The Most Advanced Next.js SaaS Stack

Bedrock, the Next.js SaaS boilerplate

It took me one year to code a SaaS tool using Next.js (πŸ₯‡ procrastination). Why? Because Next.js is just part of the challenge. You also need user authentication, team management, Stripe implementation, an API (GraphQL?), migrations, emails, ESLint, Cypress…

☝️ Bedrock has all of that and more.

The good news is: it's not free!. If you decide to go with it, you get a real product with support and updates instead of a project that'll get outdated once you start using it.

I partnered with Max (the author) to offer readers of Next.js News a 26% discount on Bedrock (you save $117) via this link:

https://gumroad.com/a/350753907/IhaSu

You can't get a better offer to kickstart your idea.

PS: If you're hesitant, there's a 14-day money-back guarantee.

Best and Most Shared Articles πŸ—ž

Build a full API with Next.js β€” Nicolas Torres is publishing excellent Next.js content that you can't find easily. This article is about building a full API using regular Next.js API routes together with next-connect, next-auth, Supertest, and ACLs.

Transitioning Mailbrew from CRA to NextJSβ€” Francesco from Mailbrew talks about the challenges and benefits of porting their create-react-app app to Next.js. Why did they do it? Because it wasn't easy to have a single domain serving their static app and API routes.

How I Built My Blogβ€” Josh shares the stack he's using to build his blog. It's an interesting article that goes into details about Next.js, API routes, and MDX.

If you write Next.js content, send it to me.

Upcoming Next.js Features

What's coming up in future versions of Next.js? Here's what I am excited about:

  • A new Babel loader. The Next.js team is working on a turboMode that, when activated, switches from next-babel-loader to a new, presumably faster, babel loader. Give it a try! PR, source.
  • Webpack 5 enabled by default for all apps without custom webpack configuration, PR
  • Font optimization is out of experimental, PR
  • Inlining critical CSS, PR, source

Are you closely following the Next.js codebase? Send me some intel :)

Feature Requests πŸ€”

Hot Discussions πŸ’¬

Best Tweets


See you next time πŸ‘‹

Fresh Next.js resources
in your inbox

Built by @vvoyer