A couple of weeks back, I developed an API in Node based on Typescript. I tried to deploy it on Heroku.
But the process was long and time-consuming. Also, I noticed that Heroku is terminating free accounts from 28 Nov'22. โน๏ธ
So I tried to experiment with various other platforms to deploy my Typescript-based Node API. Amon them free, robust, and versatile platform I found is VERCEL. Based on my experience, here are a few simple steps which you can follow and easily deploy Typescript-based Node API on Vercel. ๐
1) Express + Typescript Boilerplate App โ๏ธ
Create express project with typescript. You can follow the below-mentioned steps to make a boilerplate for the project. (Github repo link is provided at end of article)
-
Initialize node project
npm init -y
-
Install packages (you can use npm/yarn/pnpm)
yarn add express yarn add -D typescript yarn add -D @types/node yarn add -D @types/express yarn add -D nodemon yarn add -D ts-node
-
Create
tsconfig.json
To work with typescript we need to make tsconfig.json file which will help to compile and build Typescript files in plain JS. Execute below command
npx tsc --init --rootDir src --outDir build --esModuleInterop --resolveJsonModule --lib es6 --module commonjs --allowJs true --noImplicitAny true
Once the file is created you can keep it as is, or cleanup non necessary stuff. Replace content of tsconfig.json
with following :
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"target": "es6",
"noImplicitAny": true,
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"baseUrl": ".",
"paths": {
"*": ["node_modules/*", "src/types/*"]
}
},
"include": ["./src/**/*"]
}
-
Update
scripts
inpackage.json
"start": "nodemon src/index.ts",
- Write express server code : Create file :
src/index.ts
and paste following code in it
import express, { Request, Response } from 'express'
const app = express()
const port = process.env.PORT || 8080
app.get('/', (_req: Request, res: Response) => {
return res.send('Express Typescript on Vercel')
})
app.get('/ping', (_req: Request, res: Response) => {
return res.send('pong ๐')
})
app.listen(port, () => {
return console.log(`Server is listening on ${port}`)
})
- Spin up server : Run
yarn start
ornpm run start
command in terminal to start express serve. You can open browser and go tolocalhost:8080
. API will return response ofExpress Typescript on Vercel
.
2) Initialize git in our project. ๐ฅ
- Make a
.gitignore
file in the root of the folder. And addnode_modules
to it. If .gitignore file exists check thatnode_modules
is added into it. - Execute
git init
in the terminal (from root of project) or you can use VS Code's source control tab to initialize git repository. - Connect local repo to remote (github/bitbucket). You can use any of the version control system to publish your repository.
3) Create Vercel project ๐๏ธ
- Go to vercel.com -> Login
- Login using the Version control platform you have kept your repository.
From the dashboard -> Add new project -> Select your repository -> Deploy
Afer deployment you will see something similar to this! ๐
- Don't worry... Just follow on steps to fix it. ๐
4) Add Vercel config in app โ๏ธ
- In the above step, after your fist deploy is completed, you can see that we're not getting
Express Typescript on Vercel
response from API. - To work this as expected, we need to tell Vercel that is a API and you need to serve this as a serverless function.
- For this, simply we need to add
vercel.json
file in root of our project. Paste below code in file.
{
"version": 2,
"builds": [
{
"src": "dist/index.js",
"use": "@vercel/node",
"config": { "includeFiles": ["dist/**"] }
}
],
"routes": [
{
"src": "/(.*)",
"dest": "dist/index.js"
}
]
}
NOTE: Check your tsconfig.json file. The value against outDir
must be kept instead of dist
. If your config file has any other value than dist
, replace it at either of both places.
5) Add a pre-commit
hook ๐ท๏ธ
Vercel requires plain JS source files instead of Typescript. In order to do this, we need to build the project before committing and send compiled JS files so that Vercel can parse those files and serve the API.
Install
pre-commit
andrimraf
package :
yarn add -D pre-commit
yarn add -D rimraf
- Modify
scripts
field inpackage.json
file as follows:
"scripts": {
"start": "nodemon src/index.ts",
"build": "rimraf dist && tsc",
"ts.check": "tsc --project tsconfig.json",
"add-build": "git add dist",
"test": "echo \"Error: no test specified\" && exit 1"
},
- Add new field
pre-commit
field inpackage.json
:
"pre-commit": [
"ts.check",
"build",
"add-build"
]
- What this will do? โ Whenever you will commit, the commands written in pre-commit will be executed. It will check Typescript errors, build the project and add build folder to the staged changes. (If you opt for manual build, don't forget to run build command to start build.)
5) Re-Deploy and Re-Check API ๐
Commit the changes you have made and push the commit to GitHub. Check on vercel for the new deployment. Vercel will automatically trigger a new deployment on every push. Incase it is not started, you can manually start a deployment.
Once new deployment is live, you can copy the deploy URL and run in browser. You will see
Express Typescript on Vercel
as a API response. Hurrah ๐
- To assure that API is working perfectly, you can also hit
/ping
route which will returnpong ๐
as the response.
Closing comments ๐โโ๏ธ
- Thank you for following steps with me. Incase you find any issue in above mentioned steps, please ping in comment.
- Also a humble request you to write which topic you want in my next blog. I will include that in my target list. ๐ฏ
- Github repo link for this project : Express Typescript Code
Tirth Patel, signing off! ๐ซก
Top comments (36)
Thanks!
This is very helpful.
For those who's still stuck at 404 error code missing in Vercel. Just remove the ignore built ts files which is in your .gitignore file. In this case remove or comment out the dist directory.
Good catch @aliffazmi. Thank you for pointing it out. ๐
It was useful but what I donยดt undestand is why do we need to create dist directory?
That directory must be created when commit occurs but only into vercel.
How do I change the output directory in vercel.json #5081
Hi @cel2022_01,
Good question. Actually the way VERCEL works is based on plain Javascript files. It can't directly operate on Typescript code. So inorder to run our Typescript based Express App, firstly we compile TS to JS. That compiled js source files are stored in
dist
folder. The path fordist
folder is given in vercel config. So when any endpoint is hit to the server, VERCEL find the respective route in thedist
folder and processes the request accordingly.Hope this might resolve your query. Please continue the thread if more discussion is needed.
Thanks.
We understand that but why can't vercel build and create the dist itself . Why dist need to be in git after git push .
Deploying Nest and nextjs doesn't need to include dist folder in git source code .
@thanhtutzaw @cel2022_01 @gaborpinter
I am a bit late to this, but:
The exact issue is that @vercel/node package, through builds prop in vercel.json, doesn't include buildCommand from vercel.json, it just serves what's already built.
However, builds and routes commands are deprecated and it's enough to use rewrite (vercel.com/docs/projects/project-c...).
The easiest solution would be to "skip" tsc and serve API directly through api/index.ts
vercel.json will look like:
Any update on this question? Why indeed do we need to push compiled code to a "modern" platform?
Hi Tirth, I'v tried to follow your instructions but I can make my app work, I get the following error: "Due to
builds
existing in your configuration file, the Build and Development Settings defined in your Project Settings will not apply."In my app url I get the following error: "This Serverless Function has crashed".
Would you take a look at my code please?
github.com/SoozaV/sinecta-maps-bac...
Regards!
I think I found out the issue looking at my function logs:
Do you have any idea on how to solve this? I can't find a solution.
Regards.
Or you can do one more thing, in the vercel project setting page you can override the build command. You can try this one:
npm i -g pg && npm run vercel-build
This will first install pg package in your VM on cloud server. Then you can access it while calling API. Please try this as well. And let me know if it works.
Cheers :)
I've tried it, but it seems like the error persists... Normally it should work, but I don't know why it doesn't... ๐ญ
Finally, I've resolved it, not by installing pg globally with npm, but by adding the dialectModule option into my database configuration as below :
Hello, I have the same problem, I put the dialectModule: pg in the DB conifg and nothing, still with the error. I have the DB in supabase and in vercel I installed the integration with supabase to see if it would be corrected but it didn't either. I don't know what to do anymore, is there any other alternative? Thank you.
Hi @soozav It seems there is some issue with pg package. I've found one resource that might help you. Please check this PG package issue
it helped me a lot! thank you
Welcome to DEV community @fatemesoleymanian
This tutorial helped me, thank you
very useful thank you!
Many thanks Tirth. I was stuck for 4 hours. Finally I found your post and Bingo!
thank you so much, this really helpful..
Is there a way to avoid pushing the dist folder?
So Vercel will build and generate the dist folder for us
Hello! Have you found a way?
hello i followed all the steps and uploaded my repository which is connected with sequelize to postgresql but i get this error:
Error: Please install pg package manually
at ConnectionManager._loadDialectModule (/var/task/node_modules/sequelize/lib/dialects/abstract/connection-manager.js:55:15)
at new ConnectionManager (/var/task/node_modules/sequelize/lib/dialects/postgres/connection-manager.js:15:24)
at new PostgresDialect (/var/task/node_modules/sequelize/lib/dialects/postgres/index.js:13:30)
at new Sequelize (/var/task/node_modules/sequelize/lib/sequelize.js:194:20)
at Object. (/var/task/dist/db-connection.js:8:14)
at Module._compile (node:internal/modules/cjs/loader:1358:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1416:10)
at Module.load (node:internal/modules/cjs/loader:1208:32)
at Module._load (node:internal/modules/cjs/loader:1024:12)
at /opt/rust/nodejs.js:1:11506
anyone know how to fix it ?
Hi, I hope you can help me.
I follow the tutorial and a lot of tutorials more and I couldn't get the solution.
Always I receive the same error on vercel: 404 not found.
I wrote a post in StackOverflow, maybe someone can reply or if you know what i'm doing wrong, i will appreaciate. This is the post of my question: stackoverflow.com/questions/775091...
Thanks for your time
Please refer to this question stackoverflow.com/questions/765767....
I posted an anwser there.
You need to share a demo so that another person can help you.
Thanks. I didn't share a demo because I wrote my structure and my config file. with exactly all the things.