How to Deploy Fullstack React.js + nestJs + postgreSQL to Heroku

Tal Shnitzer
The Startup
Published in
6 min readNov 9, 2020

In this article we will walk through deploying a complex fullstack project:

at the start point the frontend and the backend are in 2 different libraries, and the DB is in local postgreSQL.

at the endpoint there will be one url that can be spread around for people to reach the app on their browser.

I wrote this article since I myself struggled over this, spending more time than I should have.I was going over many articles and docs, each had partial info that took me part of the way to my goal. hopefully this article will get you to the goal of a working app on the web in minimal time and effort .

PREREQUISITS

  1. GIT account + knowledge of creating and committing code to repository
  2. Heroku account + knowledge of creating an app and pushing code to it
  3. backend server coded in nestjs
  4. frontend coded in React
  5. postgres and pgAdmin installed

prepare the code for fullstack deploy

first stage is to create one fullstack app file tree containing both backend and frontend code.

this is the directory tree at the start:

git repo to start with

In the local frontend folder, create a production build.

run from the root of the project:

>npm run build:prod.

“build:prod” script is defined in package.json, at the example below the build script uses the webpack tool:

“build:prod”: “webpack -p — env production”

there will be a new library containing your build output files, according to the configuration. if webpack tool is used for the build the output directory is defined in webpack.config.js (in the below example /public/dist):

“output: {

path: path.join(__dirname,’public’,’dist’),

filename: ‘bundle.js’

},”

if create-react-app is used the build:prod script creates a directory called build and under it the same output files.

Open a new directory on your local filesystem to contain the fullstack app,(let’s call it “<app_name>_fullstack”).

copy the content of your backend under it.

copy the frontend build directory under “<app_name>_fullstack” directory.

the “<app_name>_fullstack” directory should look like that:

The backend server serves the frontend

the app should start up by running one command. in this setting the backend server is serving the frontend main page, which is the index.html file in the frontend build library.

the nestjs server needs to serve the static files that is in the build directory:

add the following code to src/app.module.ts

import { ServeStaticModule } from ‘@nestjs/serve-static’;

@Module({

imports: [

ServeStaticModule.forRoot({

rootPath: join(__dirname, ‘..’,’build’),

}),

in the frontend code: declare the url in the request sent to server as a relative url, in the example below we leave out the server address in bold, and code only the route-name.

return superagent
.post(‘http://127.0.0.1:3000/route-name')
.send({content})
.set(‘Content-Type’, ‘application/json’)
.end((err, res) => {
if (err) { console.log(‘error from server: ‘, err);}
console.log(‘great‘);
})

create a new production build and replace it with the previous one, under the root of the <app_name>_fullstack directory , same steps as explained above.

test it on your localhost. run your nestJs backend server and GET the server address on your browser.You should get your app up on the browser window.

From the root of the project directory open a new git repository i.e. “<app_name>_fullstack”, and commit the fullstack code to it.

Prepare for deployment

add scripts to package.json file:

“build”: “tsc -p tsconfig.build.json”,

“prestart:prod”: “rimraf dist && npm run build”,

“postinstall”: “npm run prestart:prod”,

“start:prod”: “node dist/main.js”

Those scripts will be run by heroku and will build a node.js compiled file named “main.js” under a dist directory in the root of the project.than the start command will be run.

add a file named “Procfile” at the root of the project, that file specifies the commands that are executed by the app on startup.

Procfile:

web: npm run start:prod

make sure the PORT is defined in our code as env var and not hard coded.in file /src/main.ts:

async function bootstrap() {

const app = await NestFactory.create(AppModule, {cors: true});

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

}

build a .gitignore file at the root of the project, define all the directories and files that are not committed.the dist directory at the root of the project should not be committed since heroku creates it at the build process..env files also should not be committed since env vars set directly on heroku.

Deploy

commit all those changes to git, create a Heroku app, and push the code to Heroku.

set env vars on heroku dashboard (can also be done on heroku cli):

Personal>app_name>settings>reveal Config Vars

Configure the below 2 env vars as shown in the pic below:

After the build has succeeded (woohoo!!) try to run the app on the url Heroku provides for the app. we will get an error since we didn’t connect the postgreSQL data yet.

Connect Heroku postgres add-on

on Heroku dashbaoard, click the app, click the resources tab, and then the “find more add-ons” button. pick the postgres add-on and then choose the plan that suits you the most. as you can see below I chose the free plan to start with.

reveal the credentials to connect to the DB: click on the Heroku Postgres add-on (see pink arrow in the pic above) and than, in the Data window that opens, click the setting tab and “view credentials” button.

Connect the DB to the server

config the credentials as Heroku env vars:

add the credentials to the backend code in the file /src/app.module.ts:

import { MassiveModule } from ‘@nestjsplus/massive’;

@Module({

imports: [

MassiveModule.register({

user: process.env.POSTGRES_USERNAME || ‘<local-postgres-user>’,

password: process.env.POSTGRES_PASSWORD || ‘<local-postgres-password>’,

host: process.env.POSTGRES_HOST || ‘localhost’,

port: 5432,

database: process.env.POSTGRES_DATABASE ||‘<local-postgres-db-name>’

}),

commit the changes and push to Heroku.

Create tables in the Heroku postgres DB.

For this one you’ll need postgres and pgAdmin (admin tool to manage postgres DB), so if you don’t have, please go ahead and install it.

Open the pgAdmin tool and create a server: servers>create>server:

on the dialog box go over 3 tabs:

General — there set a name for the server — any name you want

Connection — there set the credentials from Heroku (see pic below)

SSL — set SSL mode to “require”

Click save and you’ll see your sever connected on the server list

add tables to DB: Click your-server-name>Databases and find your database. this could be a little tedious. the databases are in ascending letter order and your database is in a different color than the rest.

Click your database>Schemas>public>Tables>Create>Table

and on the dialog box that opens define the table name, columns and any other definition you need

The End

Thats it, we’re done! now you can run the app on and operate it with database.

If you enjoyed this article, feel free to like and share.

And most important, write to me about your experience, and if you have questions or problems.

you can read about me and my work at shsh.com

--

--