How to deploy a TS Node.js app in minutes
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:
npm init
will initialize your application, but if you want to skip the questionnaire, you can also add the-y
flagnpm install express @types/express
will install express module dependency and types for the Typescript to recognize the Express class typesnpm 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 configurationtsconfig.json
filedeclaration
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 moduleoutdir
declaring output compiled TS folder, if not declared, the default compiled file location will be in the same location as thets
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 = 3000app.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:
npm run tsc
will compile your application according to the configurations in thetsconfig.json
file and create abuild
foldernpm 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:
- Copy the compiled build folder
- Copy package.json and package-lock.json files
- Install app npm dependencies by running
npm install
- 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.jsonRUN 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! :)