Deploying a Production NestJS, MongoDB(Mongoose) to Heroku Server

ISOP
ISOP Nepal
Published in
4 min readJan 23, 2019

The basic approach to hosting a Node application on Heroku is:

  1. Have your package.json the file defines any required dependencies (e.g. the dependencies that will already be there)
  2. Specify what node version you want to use in package.json
  3. Specify a start script in package.json that tells Heroku how to start your application after installing everything
  4. Push your code up to Heroku using git push heroku master

This process is pretty simple, but things get a little more complicated when we have a complex project structure that includes TypeScript and various other things for development. The only thing we want to actually “host” is the built production files (e.g. what you would find in the dist folder) not the entire project. So, we need to differentiate between what we are doing with local development and what we are doing when we deploy the application, but we don't want to mess around with configuring things every time we want to deploy the NestJS server.

Getting the NestJS Project Ready

The example I used for this tutorial was just a blank NestJS starter application, you could do the same by creating a new project:

npm i -g @nestjs/cli
nest new project-name
npm run start
// start at http://localhost:3000/

Add a new Controller

// add in src/cards.controller.ts
import {Controller, Get, Req} from '@nestjs/common';
import {Request} from 'express';@Controller('cards')
export class CardsController {
@Get('/')
getIndex(@Req() request: Request): string {
return `my first controller: ${request.method}`;
}
}// update app.module.ts
// restart node, default port is 3000
// Visit http://localhost:3000/cards/

Deploy to Heroku (Run time Build)

There are a few things we will need to configure in the project before moving on.

Modify src/main.ts to use a dynamic port:

await app.listen(process.env.PORT || 3000);

When developing with NestJS we will generally use port 3000 but this won't work with Heroku. Instead, by adding an optional process.env.PORT to the listen the method, it will use that port instead if it is defined.

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors(); // protection
await app.listen(process.env.PORT || 3000);
}
bootstrap();

For the Database connection,

@Module({
imports: [
MongooseModule.forRoot((process.env.MONGODB_STORE_URI || 'mongodb+srv://Username:Password@clustercovid-ooazl.mongodb.net/databaseName?retryWrites=true&w=majority')),
StoreModule,
UserModule,
],
})
export class AppModule {
}

we have added process.env.MONGODB_STORE_URI while setting node config

Create a Procfile file

This required because when you use free Heroku you can only execute the command npm run start by default but to run npm run start: prod based on your package.jsonwe have to Procfile file at the root level.

web: npm run start:prod
// this enable to start without using ts-node
// this will run prestart:prod automatically

Create a Heroku App

Next up, you will need to create your application on Heroku. If you haven’t used Heroku before, you will need to create a new account and you will also need to install the Heroku CLI. Once you have the CLI installed, you will need to run heroku login to log into your account through the CLI.

Once your application is created on Heroku, it is time to prepare your codebase to be pushed up to it. Assuming that you have not already been using Git for the project, you should initialize a new Git repo with:

You will then need to link it to your Heroku application using the command that was provided to you when you created the app in Heroku. It will look like this:

heroku git:remote -a MY-HEROKU-APP

Update Node Config

There are a couple of final steps we need to take before we push our code up to Heroku. First, we need to make sure that the environment is configured correctly by running these commands:

The NODE_ENV the config should already be set to production by default, but we are changing NPM_CONFIG_PRODUCTION to false. Since we are performing the TypeScript build on the server (this is what our postinstall script does) we need all of the devDependencies in package.json for it to run properly. If NPM_CONFIG_PRODUCTION is set to true the devDependencies won't be installed and it won't work.

heroku config:set NPM_CONFIG_PRODUCTION=false
heroku config:set NODE_ENV=production
// this allow us to build in heroku
if you have db connnection then set this also
heroku config:set MONGODB_URI=mongodb+srv://UserName:Password@clustercovid-ooazl.mongodb.net/databasename?retryWrites=true&w=majority

Finally, we need to update our gitignore Create a .gitignore file at the root of your project:

# Specifies intentionally untracked files to ignore when using Git
# http://git-scm.com/docs/gitignore

*~
*.sw[mnpcod]
*.log
*.tmp
*.tmp.*
log.txt
*.sublime-project
*.sublime-workspace
.vscode/
npm-debug.log*

.idea/
.sourcemaps/
.sass-cache/
.tmp/
.versions/
coverage/
www/
dist/
node_modules/
tmp/
temp/
$RECYCLE.BIN/

.DS_Store
Thumbs.db
UserInterfaceState.xcuserstate

We don’t want to push any node_modules or other junk up to Heroku, so we will make sure that doesn't get committed.

Push Your Code

Now, all we need to do is push our code up to Heroku. You can do that by running:

git commit -m "doing it live"

Whenever you want to push new code up to Heroku, just add - commit - push heroku master.

Summary

I hope this will help to deploy nest js project as this isn’t really officially documented — this is just something I’ve played around with that works for me without having to jump through too many hoops. If you have your own process for deploying NestJS applications please feel free to post about it in the comments.

Deployed project: https://nestjs-heroku-deployed-test.herokuapp.com/

--

--

ISOP
ISOP Nepal

ISOP app is your virtual classroom. Virtual classroom allows you to learn when you like, not when bell rings.