Introduction

Esbuild is a JavaScript bundler and minifier that has a huge amount of ready-to-use plugins and that shines by its amazing performance. So, for developers who are used to relying on tsc, the content of today's article may be of interest to them. Mostly because we are going to use the same tsconfig.json for the esbuild configuration base.

Prerequisites

Before going further, you need:

  • Node.js
  • NPM
  • Tsc

In addition, it is expected to have a basic knowledge of Express.js to complete the project.

Getting Started

Create project setup

As a first step, create a project directory and navigate into it:

mkdir node-esbuild

cd node-esbuild

Then we can create our development environment, as well as our TypeScript project:

npm init -y

npm install typescript @types/node --save-dev

Now we can create the tsconfig.json file and add the following configuration:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "allowJs": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "typeRoots": ["./node_modules/@types"],
    "sourceMap": true,
    "outDir": "build",
    "strict": true,
    "lib": ["esnext"],
    "baseUrl": ".",
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "moduleResolution": "Node",
    "skipLibCheck": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

With the current TypeScript setup we know three important things:

  • the JavaScript target is ESNext
  • we can use ES Modules
  • the output folder was named `build`

With this configuration of our TypeScript project done, we can move on to the next step.

Install dependencies

The next step is to install the packages needed to build the simple API. Run the command below in your terminal:

npm install express

npm install @types/express --save-dev

After executing the above commands, we installed two packages in our project, express which is a Node.js framework and its data types.

Create Express server

Before proceeding to create the API, we have to create the source code folder and the entry file:

mkdir src

cd src

touch app.ts

After this, in the `app.ts` file write the following API:

import express, { Request, Response } from "express";

const app = express();

app.use(express.json());

app.get("/", (req: Request, res: Response): Response => {
  return res.json({ message: 'Hello, World Wide Web!' });
});

const start = async (): Promise<void> => {
  try {
    app.listen(3000, () => {
      console.log("Server started on port 3000");
    });
  } catch (error) {
    console.error(error);
    process.exit(1);
  }
};

void start();

Setup esbuild

Now we need to install the necessary dependencies to configure esbuild:

npm install nodemon esbuild esbuild-node-tsc --save-dev

After executing the command, we will have the following dependencies:

  • nodemon - will be responsible for reloading the API on development environment
  • esbuild - will be used to transpile the code
  • esbuild-node-tsc - is the bridge to use the esbuild together with the tsconfig.json configuration

Note: It is worth mentioning that it is recommended to use tsc to validate data types.

Next, create a nodemon.json file and add the following configuration to it:

{
  "watch": ["src"],
  "ignore": ["src/**/*.test.ts", "node_modules"],
  "ext": "ts,mjs,js,json,graphql",
  "exec": "etsc && node ./build/app.js",
  "legacyWatch": true
}

With our dependencies installed and nodemon configured, we can move on to the next step.

How does it work?

The esbuild-node-tsc package reads the configuration from tsconfig.json and builds the app according to what is defined in the file. Nodemon is used to watch files whose extensions are defined in your configuration file and with each change, the app is reloaded and transpiled from TypeScript to JavaScript, as well as all files inside the source folder are copied to the folder build/.

After this brief explanation, we can add the following scripts to the `package.json` file:

{
  "scripts": {
    "dev": "nodemon",
    "build": "etsc",
    "start": "node ./build/app.js"
  },
}

As you can see, the following commands were created:

  • npm run dev: to run the app during the development environment
  • npm run build: to bundle source code for production
  • npm start: to launch the app in the production environment

Hope you enjoyed this tutorial, stay tuned for more.