Deploying ReactJS App on Ubuntu 20.04 LTS on Amazon EC2 instance
Tags: react, ec2, nginx, run
Published: 2022-03-17 11:57:14

React, which is also known as React.js or ReactJS, is a free and open-source front-end JavaScript library for building user interfaces based on UI components. It is maintained by Meta (formerly Facebook) and a community of individual developers and companies.

Some of the popular websites built with or using ReactJS extensively are Facebook, BBC, Netflix, Salesforce, Asana and Dropbox. According [a 2021 survey](https://insights.stackoverflow.com/survey/2021#overview) by Stackoverlow React.js (40.14%) has surpassed jQuery(34.43%) as the most commonly used web framework. [Support link](https://www.statista.com/statistics/1124699/worldwide-developer-survey-most-used-frameworks-web/)

While it could be a breeze developing an App in React, it may not be that straight-forward to deploy a React app on a Ubuntu 20.04 server, if you are doing it for first time in particular.

## Hosting on Amazon AWS

AWS EC2 is one of the popular options to host a React app. In this article we’ll see how to deploy a react app with ngnix on a Ubuntu 20.04.3 LTS (GNU/Linux 5.11.0-1022-aws x86_64) hosted as an AWS EC2 Instance.

Note: This article assumes that you have a basic knowledge of AWS cloud system and ReactJS. This article also assumes that you have already bought a domain and it is already pointed to your server, the EC2 instance and it is working.

Note: To check whether a domain is pointed correctly to a server's IP check it at https://dnschecker.org/#A/domainxyz.com (replace your domain name)

If you haven't registered a domain yet you may want to checkout [official AWS instruction](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html#domain-register-procedure) or may want to look at some other cheaper options.

## Install and Configure ngnix on EC2 instance

- Launch an EC2 instance with latest Ubuntu LTS AMI
- Connect to the console from preferred terminal through ssh:

`ssh <username>@<server-ip> -i <key-name>`

## Install nginx

`sudo apt update`
`sudo apt install nginx -y`

Once installed it should show the default nginx page when you visit your domain in address bar of browser:

![Nginx default landing page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v1vof8cig9ayixg23nv.jpg)

## Nodejs

Although Nodejs is not required to run basic ReacJS applications, it is essential if you are using the popular JSX syntax in your react app. 

Nodejs makes developers life easier by providing access to Javascript ecosystem a ReactJS uses. 

Nodejs is required if you want to use a node.js-based build tool like browserify or webpack to build nity production bundles.

### Install Nodejs

In order to install Nodejs we need `curl` to get Nodejs downloaded to our server. On a EC2 instance `curl` comes installed by default. So if `curl --version` does not show you result on your server, install it by running:

`sudo apt-get install curl`

Next, install Nodejs

`curl -sL https://deb.nodesource.com/setup_15.x | sudo -E bash -`

Test the NodeJs version and npm version

`node -v
npm --v`

## Install Yarn (optional)

Since I, personally like to use Yarn for package management in my React.js apps I would [install Yarn](https://tecadmin.net/install-yarn-amazon-linux/), using npm of course.

`sudo npm install yarn -g

## Create project

Let's create a react app using create-react-app. If create-react-app is not installed it should ask you to install it so press `y` when asked to do so.

`npx create-react-app react-tutorial`

Now go into directory and build and run, using yarn.
`yarn install
yarn run build
yarn start``

(Alternately you could run all command using `npm` by replacing `yarn` in above commands.)

After you enter the `yarn start`, you'll be able to see the react server running and the relevant ports in the shell.

![ReactJS default ports in the shell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8vqbb4rxq9gprfgabfa.jpg)

Try to access the react app at public IP for your server. For example http://172.31.3.180:3000

Note: 3000 port should be opened in the security group of your EC2 instance, as shown below. You can [add an inbound rule to the security group](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.create-cluster.console.configure-inbound-rules.html) attached to your EC2 instance.

So now, your server's public IP with 3000 port should display something like this:


![ReactJS default landing page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v93bpkpxdfinev6bddh6.jpg)

The ReactApp is now running but there is a problem. The problem is, if as you exit the ssh console, the ReactApp will stop. In order to fix this, and keep app running even if we closed or exited the ssh console, we need a process manager which would keep app running all the time, unless we ask it to stop it.

PM2 is a daemon process manager that will help you manage and keep your application online 24/7. Let's install it.

`sudo yarn global add pm2`
or
`sudo npm install pm2@latest -g`

once pm2 is installed you may want to test some of its basic commands, such as

<pre>
pm2 status
pm2 list
pm2 restart <app-name OR app-id>
pm2 stop <app-name|app-id>
pm2 start <app-name|app-id>
pm2 delete <app-name|app-id>
</pre>

To run our app run the following while being at the app folder, i.e. `react-tutorial`

`pm2 start yarn --name "React Tutorial" -- start`

Once App is started, running would yeild `pm2 list`

![PM2 list](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1j1ve9bz2w0gw9wfy8ca.jpg)

In order to start pm2 on system reboot add the following:

`pm2 startup systemd`

Now our react application will keep running in the background unless stopped anyhow.

Since we have access to our app at port 3000 we would like it to show it at the default port 80 or our Nginx web server. That also means that it has to show at the very root of our our domain name since we already have pointed our domain to this server's public IP address. 

In the next step of this tutorial we are going to see how we can use Nginx as a reverse proxy and divert traffic to port 80 i.e. the default landing page of our domain or public IP.

Create a new site config in `/etc/nginx/sites-available`

`cd /etc/nginx/sites-available`
`sudo nano react-tutorial`

The last command will open a text file to be edited. Paste the following code into it while replacing xxx.xx.. with your IP address, add domain name with space, use any one of two or both.

<pre>server {
    listen 80;
    listen [::]:80;
    
    server_name xxx.xxx.xxx.xxx yourdomain.com;
    access_log /var/log/nginx/reat-tutorial.com.access.log;                
    error_log /var/log/nginx/reat-tutorial.com.error.log;       
    location / {
            proxy_pass http://127.0.0.1:3000;
            client_max_body_size 50m;
            client_body_buffer_size 16k;
            proxy_http_version 1.1;                                              
            proxy_set_header Upgrade $http_upgrade;                              
            proxy_set_header Connection 'upgrade';                               
            proxy_set_header Host $host;                                         
            proxy_cache_bypass $http_upgrade;   
    }
}</pre>

Save and exit the file with `Ctl+x -> Y`.

Next, we need to activate this new site by creating a symlink to new site configuration

`sudo ln -s /etc/nginx/sites-available/react-tutorial /etc/nginx/sites-enabled/`

Make sure that your nginx configuration syntax is error free

`sudo nginx -t`

Restart Nginx

`sudo systemctl restart nginx`

You may want to restart your app also:

`pm2 restart "React Tutorial"`

If everything goes well you should see your app running at the root domain or your Amazon EC2 instance's public IP address.