DEV Community

Cover image for How to Deploy MERN Application on Render.com, a Heroku Alternative
Jolene
Jolene

Posted on

How to Deploy MERN Application on Render.com, a Heroku Alternative

Now that Heroku has shared plans of removing its free tiers, where else can developers like us host hobby projects?

I was researching on good alternatives to Heroku and came across render.com, railway.app as the 2 best possibilities. Of course there are many others like Fly.io and more.

Since I planned to host an app that needed WebSockets support I couldn't use Railway. Other options like Vercel also did not support WebSockets.

I hosted my MongoDB backend on MongoDB Atlas using its free Shared Plans option with only 512mb of space. It's quite limited but I only wanted to host it as an App Demo so it's fine for me.

Prereqs:

  • Github Account
  • Render Account
  • MongoDB Account
  • A Fully Functional MERN Application

Here's the my file structure:

  • If you happen to have the same file structure, the scripts would work for you
  • If your file structure is slightly different, feel free to edit the package.json scripts mentioned in this article.
(root)/
├── client/
│   ├── src
│   ├── public
│   ├── node_modules
│   ├── .env
│   ├── .gitignore
│   ├── package-lock.json
│   └── package.json
├── server/
│   ├── models
│   ├── index.ts
├── node_modules
├── .env
├── .gitignore
├── package-lock.json
└── package.json
Enter fullscreen mode Exit fullscreen mode

Setting up MongoDB Atlas

A guide on how to set up MongoDB Atlas. Get your query string, something like this MONGO_URI='mongodb+srv:...mongodb.net/mern-app?retryWrites=true&w=majority'

You will also need to add whitelist IP addresses from Render.com later as well, but for now you can add your current IP address to test locally.


Preparing our code

Since we're using WebSockets I want my frontend routes to show on my backend routes. So to serve static pages in production, add this into the server/index.js

// Create a proxy for the CRA dev server
if (process.env.NODE_ENV === 'production') {
    //*Set static folder up in production
    app.use(express.static('../client/build'));
    app.get('*', (req,res) => res.sendFile(path.resolve(__dirname, '../client', 'build','index.html')));
}else if(process.env.NODE_ENV === 'development'){
    const feProxy = proxy("http://localhost:3000", {
    proxyReqPathResolver: (req) => url.parse(req.originalUrl).path || ""
    });
    app.use("/*", feProxy);
}
Enter fullscreen mode Exit fullscreen mode

In your package.json in root, add the following scripts:
We will later use render-postbuild as our build command and npm run server as our start command.

"scripts": {
    "start": "cd server && ts-node-dev index.ts",
    "server": "cd server && ts-node-dev index.ts",
    "client": "npm start --prefix client",
    "clientinstall": "npm install --prefix client",
    "dev": "concurrently \"npm run server\" \"npm run client\"",
    "build": "npm install &&  npm install --prefix client && npm run build --prefix client",
    "render-postbuild": "npm install && NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
  },

Enter fullscreen mode Exit fullscreen mode

Another thing to take note is that your app should run without everything under devDependencies as these dependencies would not be installed in production, which could lead to errors when deploying the app.

For me, my server needed all devDependencies even on production so I moved current devDependencies to dependencies instead. My client did not need tailwind, postcss and autoprefixer in production so those could be left in devDependencies.

"devDependencies": {
    "autoprefixer": "^10.4.12",
    "postcss": "^8.4.17",
    "tailwindcss": "^3.1.8"
  }
Enter fullscreen mode Exit fullscreen mode

Once you're done with all the changes, initialise a repository on Github, commit and push changes to your Github Repository.


Deploying on Render

Creating Project on Render

Login to Render.com and head over to your dashboard.

Create a New Web Service with Render
Create a New Web Service

Connect your Github Account

  • After connecting your account you can select the repository with your project that you'd like to deploy
  • Then click Connect Image description

Setting Configurations

Remember I mentioned we would need to enter more IP addresses to MongoDb Atlas?

  • Get your Static Outbound IP addresses here and enter them into Atlas Static Outbound IP Addresses

Configuring Start and Build Commands
Start and Build Command on Render.com

Configuring Environmental Variables

  • NODE_ENV should be = production
  • MONGO_URI is the string we got from MongoDB Atlas
  • JWT_SECRET is one of the env variables my app needs, which is not necessary for your app, but this is where you add everything in your .env file when you ran the app locally. Set Environmental Variables

Next, Let Render.com deploy your site!
Click on Events > Deploy to see Deployment Logs
Things to check for

  • Ensure that Build command is successful
  • Ensure that Start command is successful If anything fails, you would have to read your logs to see what failed, a possible reason would be are that the project did not build correctly (ensure that you did npm install for both the server and client)

It may take over 10 minutes for your site to go live so go take a break in the meantime!


That's It! The site is Live! :)

Tada! It's live!

If its live and you're still having issues like a server selection error with mongo, you might want to check your MONGO_URI and ensure that you're using this env variable and not hardcoding it.


Thanks for reading, leave a comment and let me know what you think! Hope that helps with deployment! :)

Socials

Github LinkedIn Portfolio

Top comments (0)