Creating MERN Stack App and Hosting In Microsoft Azure using Create-React-App w/ Continuous Integration

Chris Fields II
12 min readOct 24, 2018

--

This article will cover how to host a NodeJS Express server that serves your Create-React-App website and has an API that communicates with a Document DB, Azure Cosmos DB in this case (We will use MongooseJS to connect). Microsoft Azure also easily supports CI with your GitHub or Bitbucket repo!

What You’ll Need My Friend:

- NodeJS: https://nodejs.org/en/download/
- Free 12 month Azure account: https://azure.microsoft.com/en-us/free/
- Yarn Package Manager: https://yarnpkg.com/lang/en/docs/install/
(I prefer to use Yarn for my web dev package management but feel free to use npm which is installed with Node by default! This article will use Yarn commands)
- Code Editor: I’m using Visual Studio Code
- Git: https://git-scm.com/downloads
- Postman: https://www.getpostman.com/

Reason for this Article:

I am building my own site as a fun project and couldn’t find a good recent resource of how to accomplish this.
You can check out my Azure hosted website here! And don’t be afraid to leave a Thought!
*Hint: its somewhat interactive, mouse around! Definitely a WIP 😁*

What You Will Learn!!

  • How to build a web server backend with NodeJS and Express that saves data to MongoDB (Cosmos DB)
  • How to create a simple frontend with React
  • How to host your server on Microsoft Azure and serve clients your React frontend
  • How to hook your Azure WebApp to your GitHub/Bitbucket repo for that Continuous Integration off the master branch

Now Lets Get Started!

First, use your favorite terminal and navigate to the directory you want to build the project in

My first tutorial. Had to make the dir😂

Next, create the root folder to hold the project and change directory into it

Configuration Time!!

Now that we are in the root directory, run yarn init -y to quickly create a package.json file at the root. This package.json will hold all the 3rd party modules our server needs to get up and running fast!

Now is also a great time to set up the version control repo with git init and add your repo’s remote (git remote add origin REPO_URL_HERE). I also added a few things to the .gitignore.

Set up git for Continuous Integration later.

Perfect! Now run git add -A to track the files and then git commit -m "Init commit" to commit the files. You should now be able to push the project to your repo with git push -u origin master . This will come in handy later as it allows Continuous Integration with your Azure web server. Simply pushing to the master branch will live update your site with the new changes without clients knowing except for getting new features(most of the time!). There are other alternatives to uploading your project onto the Azure WebApp like using FTP but that will not be covered (I haven’t tried this method myself).

Let’s Go Ahead and Set Up The Express Server. Ohh Yeahhhh!

Ok, so the brains of this project so to speak will live in a file at the root of the project called server.js. This file will tell the Azure WebApp what port the app listens to and how to respond when certain HTTP requests are made against it. Let’s go ahead and create that file now.

Going in order of the red numbers:
1. First we use the package manager to add packages to the project. Express to get the server up and running, body-parser for req.body magic, and dotenv for environmental variables accessible from process.env.

2. You can see the results after adding packages in package.json. The packages will be under dependencies. Note: I added the scripts object with a start script.

3. Create a .env file at the server root and define the server PORT.

4. Create server.js file at project root and use the installed packages.

5. After completing server.js, enter yarn start into the terminal and the server should start up and log “Wizardry happening on port 5001” or whatever you put as the PORT number!

Time to Add Some Routes to the Server and Set-Up a Basic API

The first thing we’ll do is add a GET route to the server’s root path.
This is the route that Azure will later use to serve your Create-React-App frontend!!!

At the root of the project, create an index.html file that we will temporarily use to serve to the client.

After that, we are ready to add the GET / route to server.js so we can serve clients the sample index.html we just created.

Notice lines 9–11!

Save everything and restart your server in the terminal (Ctrl+C and then re-run yarn start!).
Now we want to test if the server correctly serves our web page. For this step you can either use Postman or your favorite browser.

Postman on left. Browser on right. You may need to change the PORT number depending on where your server is running!

Awesome! We can serve a webpage with our Express server now. Lets go ahead and connect our Express server to Azure Cosmos DB and set-up a simple API to interact with the DB.

With that being said, lets go over to the Azure Portal and create an Azure Cosmos DB resource

Creating Cosmos DB with MongoDB as API in your relative location

Once your Cosmos resource is created, go to it, and in the second section under Settings, click on Connection String. In here we are going to copy values into our .env file.

We need the Username, Primary Password, and Primary Connection String!

Paste the Username, Primary Password and Primary Connection String into the respective places in .env file

The next thing we want to do is create a folder named server at the project root to hold the server-side logic. In this folder I usually put anything that has to do with a DB or utility files for server.js.

Create server dir at root of project via terminal (or however you like!)

Ok so let’s now create a file in the server directory named db-conn.js to connect to the Azure Cosmos DB and then we will create a Model with Mongoose to shape what we save into the Document DB!

First off, we are going to use a package called MongooseJS, an object modeler for MongoDB (remember we chose to use MongoDB API with CosmosDB earlier!). This package will connect us to the DB, allow us to CRUD the DB via models we create(so we know what the hell we’re dealing with) and yeah. Lets go ahead and add that package to the server by running yarn add mongoose.

Lol I got way ahead if you look at the directory. It shows where we are headed though!

This is all within the server folder!
Lets create that file db-conn.js now and use mongoose to connect to the Cosmos DB. We’ll be using those environment variables we set up earlier.
After creating db-conn.js, we will require() it in server.js, restart the server via the terminal and viola! Connection to Cosmos.

The left pane shows how we connect to the DB via mongoose and the env variables. The right pane Line 2 shows how we use the db-conn.js in the server! The bottom pane shows the terminal running after a restart and the DB connection success message!!

Awesome! Now we have a server that can serve a webpage and is connected to Azure’s cloud DB. Let’s use mongoose to create a model that we can then use to save documents into the database.

Thats it! A very simple model representing a Thought

Time to work on a simple API that uses this model to interact with the DB. Create a folder in the server dir named routes. We will have one file in this folder named thoughts-route.js. This file will be used on the server to mount the routes it defines. The routes it defines will enable the server to CRUD the DB.

The left pane and the top right pane show the 4 routes our API consists of. The bottom right pane shows mounting the thoughts-route to the server on line 11!

Ok! We can now restart the server and test out the API. Use Postman or your favorite HTTP tool and make a POST to seed data into the DB.

After the data is seeded, run the GET request (the first route in thoughts-route) to get an array of all Thoughts. You can play with the other routes and/or create your own.

That is about it for the server. To recap:
- Created server.js at project root
- Did configuration for package.json and git repo
- Created server folder to house server logic (Database connection, models, routes to interact with DB/other APIs, etc)
- Created Azure Cosmos Resource

We’ll Be Back Server! Create-React-App (CRA) Time

Let’s keep the server running in it’s terminal, open a new terminal and navigate to the project root and create a new folder named client and cd into it. The client directory is where we will house the CRA. Within the client directory, we will run npx create-react-app CRA_NAME in the terminal and then cd into APP_NAME when it is done creating.

The bracket at the top shows the commands entered to create the client directory. The brace at the bottom highlights the 2 main commands used for our CRA. We will use `yarn build` to get a minified production ready version of index.html

Now we’ll get the client ready to communicate with our backend (the server should be running in a different terminal and PORT and the CRA should also be running in a different terminal and PORT). We’ll add a package named axios to make HTTP requests to our server and a proxy variable to package.json so the client knows where to send the requests!
* Note that the package.json within the CRA separates the packages that are needed by the client only from the packages needed by server.js at the root*

Added axios as dependency and proxy attribute to package.json that points to where the Express server is running. This lets frontend communicate to backend API

Ok, now let’s create a simple React component to interact with the server API we made earlier.

We will use App.js for this. Replace it’s current contents with the below. (You will be able to copy/pasta from my GitHub!)

The App.js consists of 3 buttons to interact with the server API and lists out all of the thoughts within Cosmos DB!

Awesome! We now have a simple MERN stack application to play with, hopefully😅. I’ll gladly answer questions in the comments below if any assistance is needed!

One thing to note is that in our development environment we are running a local development server for the client on one PORT and our Express server on another PORT. If you do not have the server running while using the buttons, you will see error alerts.

However, in our production environment in Azure WebApp we will only have one web server!! This is because in production, the web server or Express server we built (server.js) will serve clients that request to (by visiting your .azurewebsites.net domain) your Create-React-App index.html.

Remember, we did an example of this concept earlier with Postman or your favorite browser and it should still be implemented for your server right now. Test it out again!

Running yarn run build package.json script to get a production ready index.html.

NOTE!! This step is purely for understanding/visualizing what is happening for later. The build folder that is created by this step is in the .gitignore and can be deleted after this step
Let’s go ahead and run the command yarn run build in a terminal within the client/CRA_NAME directory. This command uses the react build script to make a directory named build which will contain a minified bundled version of your application which is accessible via index.html. This is the file that our Express server will serve when clients browse to our site!

Now let’s make a few minor adjustments to get the app ready for production!

We are going to change the scripts in the root server package.json. We are doing this because Azure WebApp uses this start script by default when starting your server! We basically tell the server upon start “Hey, change into my client/CRA_NAME directory, install all the needed packages, build a production ready index.html, navigate back to the server root and start the server”. Easy peezy huh. We also added a dev script for development purposes since we just had to modify the start script.

We add express static middleware so the server has access to static files the client requires in client/CRA_NAME/build

EDIT:

Using the express.static middleware on the server allows the server to serve static assets from the specified directory. This middleware has a configurable option to set the index property which specifies which file to serve upon visiting the server root. By default this is set to index.html. What this means is we don’t even need to specify a GET /route handler to serve the Create-React-App client as mentioned in this article. You will find that with or without the GET / route, you can access the page. It will be served automagically as long as you decide to use the express.static middleware default options.

Expressjs docs regarding express.static middleware. This makes the below step of changing index.html sendFile() path irrelevant and you can delete the GET / route or keep it. The result will be the same.

We are also going to change the path of the index.html we use in server.js GET /. It needs to point to the client/CRA_NAME/build directory now and not the test index.html at the root of the project we created earlier. This file can be deleted if you like.

We should now be ready to commit our changes to the repo (hopefully you committed along the way unlike me 😅) and then create our Azure WebApp resource

Head back over to your Azure portal, find ‘App Services’ in the left pane, and click ‘Add’. This is the Azure resource used to host the site.

Runtime stack is NodeJS!

Once your resource is created, navigate to it and let’s go ahead and add the environmental variables from our .env file to it! We do this in ‘Application Settings’ > ‘Add New Setting’. Remember to always keep .env files in .gitignore!

Notice the 3 env vars for the DB Connection!

Go ahead and SAVE at the top left and once that is done, navigate to ‘Deployment Options’ under the Deployment section. This is where we will connect our repo to the resource so the resource can pull our code from the master branch!

Once you have successfully followed the GUI and connected your repo you can see your commits on master in ‘Deployment Options’, manually sync, etc. This is where the magic happens when you push to master!

The app is currently syncing my master branch. Lets hope this works😁

Let’s check out Kudu, an “Advanced Tool” we can use to see info on the cloud server our app is running on. It says “Advanced” but it can be easy to use for purposes like ours. We are going to use Kudu to look at our filesystem for the app and make sure that the client successfully installs its needed modules and creates the build folder.

NOTE: pushing to master will run the start script which installs modules and builds every time to my belief so far. This while cause your site to respond with Service Unavailable while it is down and building the client again if clients try to access it so plan to push to master at low use hours. There are advanced options you can use to get around this like multiple deployment slots!

To access Kudu scroll down to the section ‘Developer Tools’ and click ‘Advanced Tools’ and Lets a Go!

How to get to Kudu

You will land on a page that looks something like this and contains details about your app

The homepage for Kudu. Notice how it is the same URL as your website but with .scm. thrown in there!! Use this to easily nav back and forth

Now navigate to Files > url_stuffs/site > url_stuffs/wwwroot and you should notice a directory structure just like in development! I use this to tell if the site has built the client directory build or not. Site up time is another useful one!

Once you notice your client has successfully ran the build and installed node_modules you should be good to go.

The WebApp file structure within Kudu

A good way to navigate to your site is through the ‘Overview’ section in the Azure portal for your resource via the ‘Browse’ button.

And there she is! A beautiful result. You can visit this page at https://mern-azure-example.azurewebsites.net/

The site page hosted on Azure!

I like how anyone can just nuke all the Thoughts. Nice…nice 🤪. Knowing that, how much thought will you put into the Thought you post? And if someone nukes them, would it truly be time wasted?! Don’t forget to leave a more permanent Thought over at my website https://wickedworlok-therollingtray.azurewebsites.net/! Whatever is on the brain.

I hope this article helps someone. Till the next one, Peace.

Helpful Links:

--

--

Chris Fields II

I am a fullstack developer currently building the new GameStop mobile app & writing my experiences