How to Deploy a MERN Stack App to Azure via Continuous Integration

Atilla Tuna Sogut
6 min readDec 31, 2019

--

This tutorial explains how to configure a MERN app to work on Azure Web Services and how to deploy it via GitHub + continuous integration. The tutorial works off of an azure ready MERN app that I’ve built.

Note: This tutorial does not cover how to set up a full CRUD MERN app or how to develop in React. The only data we will send from our backend to our frontend is a small dictionary object.

Great Additional Resources

If you want to learn about creating full CRUD MERN apps or developing in React, I recommend the following resources. If not, skip to the next section.

Really awesome article on deploying a MERN app to Azure via CI (covers more than this article but is a bit different)

Microsoft’s own MERN Azure tutorial

For a full production ready React app

Let’s get started

Prerequisites

  1. Azure account
  2. Git + GitHub account (for continuous integration)
  3. MongoDB Atlas account (free tier) (You can also use Azure’s own CosmosDB instead of MongoDB Atlas but this tutorial does not cover it)

First Steps

  1. Clone repo at [https://github.com/Sogutt/Azure-MERN-Boilerplate]. This is the Azure ready MERN app boilerplate.
  2. Run “npm install” in root directory.
  3. Run “yarn install” in client directory.
  4. Adjust the MongoDB connection URL in new-index.js to the connection URL you get from MongoDB Atlas. If you don’t know how to do this, go to your cluster on MongoDB Atlas, click the “connect” button and follow the steps below.
Select the middle option: “Connect Your Application”
You’ll see your connection URL. Copy this into new-index.js and replace the <password> with your actual password. You can now connect to your own MongoDB database!

The last MongoDB item to modify is the database name on line 12.

Once you modify the MongoDB URL + database name, and install the packages in both the root and client directories you are all set to develop off of this template. Just make sure to run “npm run build” after any change in the client directory before you deploy to Azure. Otherwise the changes will not be reflected on Azure.

1. Project Structure & Logic

The structure is just one app (frontend-React) inside another (backend-Node/Express). The root directory contains our backend logic along with all the necessary modules. The client directory contains the entire frontend app with all the packages necessary for our React app to run. To emphasize that these are essentially two separate projects, I’m using npm to manage the backend app and yarn to manage the react app.

Since the value-add of this template is providing an Azure ready environment, the API logic (backend-frontend communication) is very straightforward. Our MongoDB contains a simple dictionary (as seen below). We retrieve this data and send it to our frontend React app to render it.

Some think that there are shows better than The Mandalorian. They are wrong because no other show has baby yoda.

2. Dev vs Prod Environment

There are 3 main differences between a local development environment and an Azure production one.

First, we need to ensure that we are not hard coding our port in server.js, because this will not work up on Azure. Instead, we determine the port in the following manner.

app.set('port', process.env.PORT || 5000);
console.log("++++++++++++++++" + app.get('port'));

The second difference is that in Azure, our frontend is served up as a static React build. This means we need to run “npm run build” in our client directory and then include the following line of code in our server.js. This enables Express to serve up the build we just created, which is how we serve up our frontend up on Azure.

app.use(express.static('./client/build'));

Third, we need to point our GET/ route in server.js to the index.html in our build.

app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build",
"index.html"));
});

Now we can deploy.

3. Setting up Continuous Integration

Note: You need to set up an Azure Web App before this step. It is a very straightforward process so I don’t think there is much to cover. However, make sure your runtime is Node 12.0 LTS. If you have already setup your web app with a different runtime, you can change it in Configuration -> General Settings.

Once you have you web app set up, navigate to “Deployment Center”.

Select the “GitHub” option. You may need to authorize if this is your first CI setup.
Select “App Service build service”
Select the project repo form your own GitHub
You’ll come to a page that looks something like this. This is where you can keep track of your deployment history and also see which version of your app is active.

Once the Status column reads “Success(Active)” the deployment is complete. You can navigate to the website via the Browse button on the top left. You will see a very bare-bones webpage where we are simply listing out the elements in our dictionary object we got from MongoDB.

Let’s do a quick demo to test out our CI. We’ll add a small bit of text, “First Continuous Integration Demo”, on line 40 in App.js. Because we have changed our react app, we need to run “npm run build” inside our client directory. If you recall, this static build is what we serve with Express on Azure.

Once we have our new build, we can push to our repo as usual. Once the push is complete, Azure will automatically redeploy the app (although you might to refresh to see the change). In the two screenshots below you can see how the Azure Deployment Center page is synced up with our GitHub repo. The message we committed with, “continuous integration demo”, is shown so we can keep track of the latest version of our app that is deployed and active on Azure.

Finally, we see that our change has been reflected in our actual app!

I hope you found this tutorial helpful. If you have any questions let me know in the comments!

--

--