Build a REST API using Node with typescript, pm2 with load balancer, webpack for development and production mode and testable with mocha/chai and supertest

Ahmed Khalil Bejaoui
6 min readJul 12, 2019

Ahmed Khalil Bejaoui — https://abejaoui.com

Node, Typescript, pm2, webpack, REST API

In this article we will build together a Rest API using Node, Express in typescript, webpack to check and transpile our code and pm2 to start and handle our processes. We will go a little bit deeper talking about best practices and needed security.

Also we will build a webpack configuration for development and production mode.

Next we will take a deep look at pm2 process manager, why and how to use it for logs management, implement a load balancer using clusters, monitor our application and run it in different environments.

Goals:

  • Build and design a Node structure with typescript and Webpack
  • Implement and explain best practices regarding lint, also thanks to some plugins security
  • Handle logging, process management and different environments with pm2
  • Add Winston logging as an express middleware and use it in development
  • Add Mocha/Chai testing and finish package.json scripts.

The final work can be accessible in this git repo.

Pre-requisites:

  • Make sure you have node installed. In my opinion the best way to do that is to use Node Version Manager. It makes it easy to switch and test in different versions of Node and npm. The documentation and the cli are pretty clear.
  • Make sure you have tslint/eslint and typescript installed by running this command
# Install the global CLI and its peer dependency
yarn global add tslint typescript
npm install tslint typescript -g
# Generate a basic configuration file
tslint --init

Create the project

Just start by creating a folder for your project, for this article we will call it api-rest.

First thing to do is to run npm/yarn init in your terminal.

# creates a package.json to handle all our dependencies and scripts
# it will asks you different questions like project name, version, licence, ...
npm init or yarn initalso can be done withnpm init -y or yarn init -yif you want to answer all questions with yes and get the default configuration.

then we can run tslint --init command in here to generate tslint.json, then create a tsconfig.json files.

  • tsconfig will contain typescript configurations
  • module: specify type of code module generation. we will use es6 but feel free to use any other type.
  • noImplicitAny: checks all declared function arguments, they should all have types or at least any as a type.
  • target: specify Ecma script target version.
  • outDir: destination folder
  • sourceMap: Generates corresponding .map files for the browser. we have to disable this in production mode.
  • allowJs: source code can contains ts and js files
  • includes contains the path to all the files for the transpiling process and excludes contains the list for the files that have to be excluded, like node_modules and test files.

For the production mode we only need to do this:

i only disabled the source map but of course a lot of other configurations you might need can be found here.

Tslint helps a lot for a better, consistent and cleaner code, try to consider it as a life saver that prevents you from jumping from the nearest window.

With the right plugins you can take care of a lot of security issues also while coding. In my next article i will talk about this file and explain every single line in it, why we need it and what we can add to enhance security.

Let’s change the auto generated file with this now:

Install all needed dependencies

I will use yarn but feel free to use npm.

So let’s start by installing all the missing plugins we added to tslint.

yarn add tslint-consistent-codestyle tslint-defocus tslint-eslint-rules tslint-origin-ordered-imports-rule -D # -D stands for devDependencies or --save-dev with npm

Next we should install and configure webpack

yarn add webpack webpack-cli webpack-node-externals webpack-shell-plugin fork-ts-checker-webpack-plugin @types/webpack

To configure webpack you just need to create a new file and name it webpack.config.js. Just copy this code and place it in this file and everything will be explained inside.

Now we should install Express and the body-parser for our API by running

yarn add express @types/express body-parser @types/body-parser
Photo by Kevin Ku on Unsplash

Let’s start coding

source structure
  • www.ts will contain our server code
  • index.ts will handle middleware, routes and controllers

Winston Logging

winston is designed to be a simple and universal logging library with support for multiple transports. We will use Console transport for development mode but also we can implement email transport or another service for production mode. To install it just run

yarn add winston

we will start by creating an utils folder under src, and create a file named winston-logger.ts and past this code in it

index.ts

www.ts

To test what we have done until now, we should start taking care of our package.json scripts. You will notice this “_comment_”, it is just there for commenting purpose, please delete when use.

To be able to spin our code for test we should take care of pm2 config. In the root of your project create a folder config and the structure will be exactly like in the photo below.

  • pm2.config.js will contain the common config in the two environment to avoid duplication.
pm2.config.js
pm2 ecosystem file for development environment

For the production ecosystem file we will add the load balancer using the cluster mode.

pm2 ecosystem file for production mode

And finally we can see what we’ve done until now, so let’s run

#dev mode
yarn start:dev
#prod mode
yarn start:prod
#list current processes
pm2 list
#monitor your api and see logs and all kind of information, just #open a new tab and run
yarn monitor
yarn start:dev
yarn monitor

Now let’s write tests, and for that we will have to install Mocha.

Mocha/Chai tests

Mocha/Chai is javascript test framework, but to have all what we need exactly we should install supertest for it’s agent that handle http requests.

To install it

yarn add mocha chai supertest ts-node @types/chai @types/supertest @types/mocha -D

then let’s create a folder named test in the root of your project and create a file for a new test. i will create a file named helloWorld.test.ts and go ahead and write this

to spin the test and check what we’ve done until now, let update the package.json test script by adding

"test": "TS_NODE_PROJECT=config/test/tsconfig.test.json mocha -r ts-node/register test/**/*.test.ts",Where config/test/tsconfig.test.json is tsconfig compatible with ts-node to avoid all kind of errors like "Unable to compile typescript" or unexpected syntax. this will do the job{
"compilerOptions": {
"module": "commonjs",
},
}

Now let’s run yarn test and check the result

Test passes

What’s next

I will create more Typescript node.js projects by following this boilerplate. we will explore swagger and docker and use them to build our way to micro services.

--

--