avatarRichard Oliver Bray

Summary

The web content provides a comprehensive guide on setting up a Node.js 16 API using Express, TypeScript, and SWC for transpilation, with instructions for configuration, testing, and optimization for performance.

Abstract

The article outlines the process of creating a Node.js API with TypeScript and Express, emphasizing the use of the SWC compiler for efficient TypeScript transpilation. It begins with the installation of necessary packages, including Express, TypeScript, and SWC, and proceeds to detail the configuration of TypeScript via tsconfig.json, the setup of Node.js version management with .nvmrc, and the creation of build and development scripts in package.json. The guide also covers the creation of a .swcrc file for SWC configuration, testing the setup with a simple "Hello World" endpoint, and running the server in both development and production modes. The author concludes with final thoughts on debugging and the rationale behind transpiling TypeScript to JavaScript for production, suggesting that while Node.js can read TypeScript files using tools like ts-node, using plain JavaScript can offer better performance.

Opinions

  • The author expresses surprise that in 2021 there isn't a CLI tool or script readily available for setting up a Node.js project with TypeScript, indicating a gap in the tooling from a frontend developer's perspective.
  • The author suggests that using SWC for transpiling TypeScript to JavaScript is preferable due to its performance benefits over other alternatives like tsc.
  • The author recommends using Node.js's native debugging capabilities with source maps for a better debugging experience, highlighting the need to convert TypeScript to JavaScript for this purpose.
  • The author opines that while it's possible to run TypeScript directly in Node.js using ts-node, it's better to transpile to JavaScript for production to avoid additional processing and achieve maximum performance.
  • The author humorously suggests that for a "super performant API," one might consider writing it in Go, implying that Go could be a more efficient language for APIs than JavaScript or TypeScript.

How to set up a Node 16, Express & Typescript API

I’ve been working on changing up one of my python projects to typescript and it surprises me that in 2021 there isn’t a CLI tool or script that can set this up for you already. You can tell I’m from the frontend world 😃

Anyway, I’ve put this article together to help others who want to do the same and use the latest build tools to do so.

Explanation video 📹

https://youtu.be/7EeGHUs4zfs

Note: The steps below are quite brief, if you want more of an explanation watch the video.

Install Packages 🎁

  1. Create a new directory mkdir <my-awesome-project>
  2. cd into that directory and initialise npm with all the defaultsnpm init -y
  3. Install Express npm i express
  4. Install Typescript with the express and node types npm i typescript @types/express @types/node -D
  5. We’re going to use SWC to transpile the TS to JS for prod so install all of these things npm i @swc/cli @swc/core -D
  6. We’re going to use Nodemon to watch the dev environment, you can install it withnpm i nodemon -D

Setup configs ⚙️

Right, that should be most of the packages installed. Let’s do the other stuff.

  1. Automatically generate a tsconfig.json file by running npx tsc --init. You’re welcome to delete the comments if you want but I find them helpful.
  2. In your tsconfig.json file change: - "target": "es5" to "target": "ES2020" - "module": "commonjs" to "module": "ES2020" - uncomment to "isolatedModules": true

3. Create a .nvmrc file with the version of Nodejs you are using like this:

// .nvmrc
16.11.1

4. In your package.json file remove the scripts section and replace it with this:

// package.json
"scripts": {
  "build": "swc src -d dist",
  "build-dev": "npm run build && NODE_ENV=development node --inspect dist/index.js",
  "dev": "nodemon --ext ts --exec \"npm run build-dev\"",
  "start": "npm run build && NODE_ENV=production node dist/index.js"
},

5. Also in your package.json file add the following line to the bottom, (or anywhere it doesn’t really matter)

"type": "module"

6. Create a .swcrc file and add the following code

{
  "jsc": {
    "parser": {
      "syntax": "typescript"
    }
  },
  "env": {
    "targets": {
      "node": 16
    }
  }
}

Testing the results 🧪

Now let’s check everything works.

  1. Create a new folder in the root called src/
  2. Create a file in src/ called index.ts
import express from "express";
const PORT = 3000;
const app = express();
app.get("/test", (req, res) => {
  res.status(200).send("Hello World");
});
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

3. Run the following command npm run dev . With the combination of Nodemon and SWC when you change some code the update is almost instant!

4. In the address bar of your browser type http://localhost:3000/test to see Hello World on the screen.

5. Stop the dev server and run npm start to build the code for production. Like the dev server, this should create a new folder called dist in the root with the compiled code.

6. Once again navigate to http://localhost:3000/test to see the code running.

From here on you can setup testing with Jest or Mocha/Chai, add Prettier, eslint, and even some Git hooks with Husky.

Final thoughts 🤔

  1. Debugging — I know I mentioned in the explanation that the --inspect flag in the dev script allows you to add breakpoints and debug the code which is true, but what I failed to mention was that breakpoints can only be added to .js files NOT .ts. This is because node can only read ts files. We’d need to use source maps which can be done in the .swcrc file with the following line "sourceMaps": true, or the package json file swc src --out-dir dist --source-maps .
  2. Why convert to JS at all — This is a valid question since it’s just an API, none of the source code is being downloaded by a user’s browser therefore, what’s the point in converting to JS at all if it’s possible to read TS directly. At the end of the day, NodeJS reads JS files, and even though ts-node can read TS files, it does so by converting them to JS. It is entirely possible to use ts-node in production and I’m sure many have, but if you want to maximise the performance of your NodeJS API, it’s best not to add any extra processing no matter how small it might be. Also, if you want a super performant API you should probably write it in Go 😸

Anyway, that’s enough talking from me. Have fun, and happy coding 👋

Typescript
Nodejs
Swc
Nodemon
API
Recommended from ReadMedium