How to deploy a TS Node.js app in minutes

Eran Amrani
Nielsen-TLV-Tech-Blog
4 min readJan 31, 2021

As a Fullstack developer creating new applications is always fun and exciting; designing the architecture, brainstorming, coding, etc. But after all the coding ends and the fun goes away, what is the next step?

One of the mistakes I saw through the years is when you are ready for publishing your app, is doing it “quick and dirty” by relying on the default configuration and missing important steps that lead to a mess in your distribution code by including unnecessary files (TS files for example).

Initialize a New TS Node.js application

If you’re already familiar with creating a TS Node.js application, you can skip this part and go to the “Distributing Your Application” section.

First Steps:

In Nielsen, we absolutely love TS, and we use it in all of our new applications, so initiating a new TS project isn’t new to us ;).

Let’s start with the basic steps of doing that:

  1. npm init will initialize your application, but if you want to skip the questionnaire, you can also add the -y flag
  2. npm install express @types/express will install express module dependency and types for the Typescript to recognize the Express class types
  3. npm install typescript --save-dev will install Typescript as a development dependency
mkdir my-app && cd my-app
npm init -y
npm install express @types/express --save
npm install typescript --save-dev

3. TS configurations

  • npx tsc — init will create and define a Typescript default configuration tsconfig.json file
  • declaration adds files that describe the shape of an existing JavaScript codebase to TypeScript during the compilation phase. This helps IDE’s to integrate properly with your module
  • outdir declaring output compiled TS folder, if not declared, the default compiled file location will be in the same location as the ts source file.
"compilerOptions": {
...
"outDir": "build", // Types should go into this directory.
"declaration": true // Generate d.ts files
}

4. Create server.ts file

import express from 'express'const app = express()
const PORT = 3000
app.use(express.json())app.get(‘/’, (req, res) => {
res.send(‘Hello World!’)
})
app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`)
})

After finishing the first steps, your application structure should look like this:

.
├── node_modules
├── package-lock.json
├── package.json
├── server.ts
└── tsconfig.json

Our next step will be to build and deploy a compiled version of our app. In production, we don’t run a TS version, but we run the compiled JS version.
Let’s see what we need to do to get there:

Let’s run these steps:

  1. npm run tsc will compile your application according to the configurations in the tsconfig.json file and create a build folder
  2. npm run start:prod will invoke the compiled server file
"scripts": {
"tsc": "tsc",
"start:prod": "node build/server.js"
}

Distributing Your Application

There are a couple of ways to distribute your compiled TS application to various environments, here we are going to discuss two main methods:

  • Npm module package dependency
  • Docker containers

Npm module package dependency

Lifecycle Scripts:

Some special life cycle scripts trigger pre/post scripts. Here we are going to use the “prepare” (supported from npm@4.0.0) cycle script, which is triggered once before publishing the package to npm registry by running the npm publish command.

files:

This optional “files” property is dedicated to declaring which entries should be included when your package is installed as a dependency. Omitting this field will make it default to ["*"], which means it will include all files.

Since we don’t want to include our TS source files, we’d want to prevent that evil default 😈

npm publish

After we finish declaring all the appropriate package.json publish configuration, let’s run the command npm publish and launch our app to the open-source community.

"main": "build/server.js",
"types": "build/server.d.ts",
"files": [
"build",
"package.json",
"package-lock.json",
"README.md"
],
"scripts": {
"tsc": "tsc",
"prepare": "npm run tsc" // compile TS by to ts.config
}

Docker Container

To publish our application in a containerized environment, we need to start by creating the docker configuration file Dockerfile in the root app folder.

These are the basic steps to get our app up and running:

  1. Copy the compiled build folder
  2. Copy package.json and package-lock.json files
  3. Install app npm dependencies by running npm install
  4. Start your app command node build/server.js
FROM mhart/alpine-node:12.16.3 // NODE VERSION
ARG NODE_ENV=production
ENV NODE_ENV $NODE_ENV

COPY ./build /build
COPY ./package.json /package.json
COPY ./package-lock.json /package-lock.json
RUN NODE_ENV=$NODE_ENV npm install
CMD ["node", "build/server.js"]

Now, let’s build our docker image in the root folder and run the build command docker build --tag my_app:test .

Run the container image and start the application server by running docker run -it my_app:test and our app is up and listening on port 3000

Summary:

In this post, we’ve covered the basics of creating a TS Node.js application and deploying it. I hope everything was clear and you now feel comfortable to start deploying your ts apps safely :)

If you have any questions, I’m here and also on LinkedIn.
Thanks for reading, and if you enjoyed it, feel free to clap! :)

--

--