A guide on setting up a Node.js project with TypeScript, Express.js, ESLint, Prettier, ts-node, nodemon and package.json environment specific scripts.

Shubham SharmaShubham Sharma
7 min read

This guide covers the complete details of setting up a Node.js project with Typescript, at the end of the blog you will get a full working codebase that contains all the essentials required for starting up a Node.js TypeScript Project.

We will cover the following things as we move on:

  1. TypeScript Node.js Express Project Setup

  2. ts-node and nodemon Setup

  3. Package.json Start Scripts For local, development, qa and production environments

  4. Dotenv Global Configuration

  5. TypeScript Build Configuration

  6. Linting For Static Code Analysis

  7. Prettier For Code Formatting

Prerequisite

  1. Node.js LTS Version 18.19.0 or above. If you don't have already, you can check nvm to install Node.js.

  2. Code Editor Visual Studio Code.

TypeScript Node.js Express Project Setup

Follow the below steps to create a new Node.js Typescript and Express.js project on the system:

  • Choose the directory in which you want to place your project or create a new one using mkdir command and go inside the project directory using cd command.
mkdir typescript-node-setup
cd typescript-node-setup
  • Now we install the required dependencies to create a typescript node and express the project, open the terminal in the project directory we created above and run the below commands. These commands will create a package.json file with all the details.
npm init -y
npm i -D typescript @types/node @types/express @types/helmet @types/cors
npm i express helmet cors
tsc --init
  • Now open the project in Visual Studio Code(VSCode) using the command.
code .
  • Now that we have installed the required dependencies, we will create an express.js app server. Create a new directory src and a file server.ts and copy and paste the below express.js server code.
import express, { Application, Request, Response, NextFunction } from "express";
import helmet from "helmet";
import cors from "cors";

const app: Application = express();

// Express Middlewares
app.use(helmet());
app.use(cors());
app.use(express.urlencoded({limit: '25mb', extended:true }));
app.use(express.json());

// Root Route
app.get("/", (req: Request, res: Response) => {
  res.status(200).json({ message: "<h1>{TS-NODE-EXPRESS}</h1>" });
});

// Server Health Check
app.get("/health-check", (req: Request, res: Response) => {
  res.status(200).json({ message: "Server is up and running!" });
});

// Start the server
const port = process.env.PORT || 3000;
app.listen(port, () => {
  console.log(`Server is listening on port ${port}`);
});
  • Now run the project typescript project using the below command. When you run the project using the below command it will create a new file named server.js. start
tsc -p .
node src/server.js

If you have successfully followed all the above steps, then let's move forward and make it a production-level server. If not, you can drop in the issue you are facing in the comments section or just google it ๐Ÿ˜ƒ.

ts-node and nodemon Setup

Now let's setup ts-node and nodemon in the project, follow the below steps:

  • Add start script in package.json file with nodemon and ts-node options.
"start": "nodemon --watch \"src/**\" --ext \"ts,json\" --exec \"ts-node src/server.ts\""
  • Execute npm start to run the project with nodemon and ts-node. nodemon watch the project files(.ts,.json) for changes and restart the server and with the help of ts-node you can execute the typescript in development without creating the build.

  • Let's create a new file nodemon.json put the nodemon command and also add some other configuration options inside the file.

{
  "ignore": ["node_modules/**", ".git"],
  "watch": ["src/**"],
  "ext": "ts,json",
  "inspect": true,
  "verbose": true,
  "exec": "ts-node src/server.ts"
}

Package.json start scripts for local, development, qa and production environments

We have added start script in package.json file to start the project using npm start command, similarly, we can setup environment-specific start scripts in our project.

Generally, an application contains four environments:

  • local (developer local system environment)

  • development (development server)

  • qa (QA server)

  • production (production server)

Apart from the above four environments, some applications also Staging/Pre-production environment, but in this project we are going to cover only four environments.

Now we will create package.json start script for env: local, dev, qa and prod, add the below code in package.json start script

"local": "NODE_ENV=local nodemon",
"dev": "NODE_ENV=development nodemon",
"qa": "NODE_ENV=qa nodemon",
"prod": "NODE_ENV=production nodemon"

For now, we are adding NODE_ENV and nodemon for all env's, we will modify the above scripts further.

Dotenv Global Configuration

To keep secrets out of the codebase, we use dotenv to load environment variables from .env file defined in the root directory of the project.

Follow the below steps to setup the global dotenv preload configuration:

  • Create a new file .env in the root directory of the project and add server PORT env variable.
PORT=3000
  • Install dotenv dependency.
npm i dotenv
  • Modify exec command in nodemon.json file to preload dotenv configuration using -r command.
"exec": "ts-node -r dotenv/config src/server.ts"
  • Now run the below command to execute the server, which will execute the server for local env and 3000 port from the .env file.
npm run local

TypeScript Build Configuration

TypeScript is used for type checking and type safety. We are using ts-node for the local environment, for production we should compile the TypeScript code to JavaScript code. For this, we can use the tsc aka TypeScript Compiler which compiles the TypeScript code to JavaScript using the options/configuration defined in tsconfig.json file.

Modify the outDir option in tsconfig.json file and add the below key for dist property, which will contain build files:

"outDir": "./dist",

Also, modify the package.json file and add a new start script to clean(rm -rf dist/), build(tsc -p tsconfig.json) and start(node -r dotenv/config dist/server.js) the project.

"build:start": "rm -rf dist/ && tsc -p tsconfig.json && node -r dotenv/config dist/server.js"

Let's also modify the start scripts: development, qa and production to reflect the build configuration instead of nodemon.

"dev": "NODE_ENV=development npm run build:start",
"qa": "NODE_ENV=qa npm run build:start",
"prod": "NODE_ENV=production npm run build:start",

Now the nodemon will be used only for the local(developer) environment, for rest of the server environments(dev,qa,prod) we will use build configuration. You can further modify the start scripts according to the project's needs.

Linting For Static Code Analysis

ESLint is a static code analysis tool which helps us find problems that may break the code in runtime environments. Let's quickly do the setup of ESLint in the project.

  • Install required dependencies.
npm i eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
  • Add .eslintrc file in the root directory of the project and copy and paste below content.
{
  "parser": "@typescript-eslint/parser",
  "extends": ["plugin:@typescript-eslint/recommended"],
  "parserOptions": { "ecmaVersion": 2015, "sourceType": "script" },
  "rules": {}
}
  • Now add the below start script in package.json that will be used to execute the ESLint.
"lint:no-fix": "eslint src/**/*.ts",
"lint": "eslint src/**/*.ts --fix"
  • Now to test the setup, let's add an unused variable in server.ts file.
let unusedVar;
  • Now execute the command to test ESLint.
npm run lint:no-fix
  • The following error will be displayed.
/home/ubuntu/typescript-node-setup/src/server.ts
  1:51  error  'NextFunction' is defined but never used  @typescript-eslint/no-unused-vars
  6:5   error  'unusedVar' is defined but never used     @typescript-eslint/no-unused-vars

โœ– 2 problems (2 errors, 0 warnings)

Prettier For Code Formatting

Prettier is used for consistent code formatting and styling. It's a helpful tool for developers working in teams avoiding code formatting, styling, and indentation issues.

Prettier Setup:

  • Install prettier dependency.
npm i prettier
  • Create .prettierrc config file.
{
  "semi":true,
  "trailingComma":"es5",
  "singleQuote":true,
  "printWidth":120,
  "tabWidth":2
}
  • Now add below start script below in package.json that will be used to execute the prettier.
"prettier": "prettier --write ."
  • Now, to test the prettier configuration, change the indentation of any line in the server.ts file and execute the below command.
npm run prettier
  • The above command will format the server.js file.

Please find the complete codebase of the project in this git repo.

To sum it up, following this guide for creating a Node.js project with TypeScript, Express.js, ESLint, Prettier, ts-node, nodemon, and tailored start scripts is like building a supercharged toolbox for developers. It helps make code better, easier to work with, and speeds up the whole development process. Using these tools together sets you on the path to creating strong, scalable, and effective Node.js projects, giving you a solid base for production-grade projects.

0
Subscribe to my newsletter

Read articles from Shubham Sharma directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Shubham Sharma
Shubham Sharma

I am a seasoned software engineer with over 5 years of experience, specializing in JavaScript technologies like Node.js and React.js. My passion for technology fuels my drive to continuously learn, adapt, and create impactful solutions that meet the needs of users and businesses. I excel in designing and developing high-performance, secure, and scalable components and APIs. Collaboration and clean code are at the core of my approach, ensuring that I deliver value to clients through best practices and a customer-centric mindset.