April 25, 2021 | Issue #4 | Share
π 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.
(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:
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/..).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:
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.
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.
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:
You can't get a better offer to kickstart your idea.
PS: If you're hesitant, there's a 14-day money-back guarantee.
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.
What's coming up in future versions of Next.js? Here's what I am excited about:
turboMode
that, when activated, switches from next-babel-loader to a new, presumably faster, babel loader. Give it a try! PR, source.Are you closely following the Next.js codebase? Send me some intel :)
See you next time π
Built by @vvoyer