DEV Community

A B Vijay Kumar
A B Vijay Kumar

Posted on

Platform Engineering with Pulumi Episode 2: Build and Deploy a React.js Application

Platform Engineering with Pulumi Episode 2: Build and Deploy a React.js Application

A guide on how to build the application and deploy it manually.

In Chapter 1 of this blog (please refer here) we built an AWS landing zone for our React.js/Node.js application. In this episode, we will build the application and deploy it manually. In the next chapter, we will use GitOps based automated deployment of both the Infrastructure and application code.

The app that we will be building is a very simple web application, that creates and fetches contact details to/from DynamoDB.

In Chapter 1, we already created a DynamoDB with Pulumi. Here is the snippet of the code, that creates the DynamoDB:

The above Pulumi code in Python creates a table called contacts-table with 2 attributes ContactName and ContactNumber, with other important configurations such as hash_key, secondary_index tags etc.

Now let's build and deploy our application, on the landing zone we created with Pulumi.

Node API

To access and perform the add and fetchAll operations on the Contacts database, let's build a simple express Node.js application. You can find the source code here.

We could have used Next.js to do both API and App, but I wanted to demonstrate deploying multiple tiers (in a typical tiered web architecture). So please play along 🙏

In this Node.js application, we will expose 2 endpoints:

  • /fetchAllContacts: This will connect to DynamoDB and fetch all the contacts and returns as a JSON response

  • /addContact: This endpoint accepts the ContactName and ContactNumber as parameters and adds the record to DynamoDB

    The use case and code is very simple, as our focus is more on the IaC and GitOps, I have kept the application very simple, with no security/login and serious exception and log handling, etc.

Let’s walk through the code quickly:

Line 1–5: We are importing express, to create the endpoints and cors. For the React.js application to call these endpoints, the URL domains will be different, as the ports are going to be different. So we will need to configure Cross-Origin Resource Sharing.

Line 7–11: In the above code, we are initializing the aws sdk, and setting the default region, and creating a DynamoDB Client object.

Line 17–28: We are creating an endpoint /fetchAllContacts using express, and fetching all the records from DynamoDB, using Scan. This fetches all the contacts.

Line 30–49: We are extracting the contactName and contactNumber from the request object and adding it to the DynamoDB table.

Line 56–61: We are then running the Node.js application listening on a port.

Please note that in Episode 1, we opened port 80 SecurityGroupIngress. In the recent code, this is edited to open 8081 for the Node.js applicaton and 8082 for the React.js one. Please refer to the latest Pulumi code on my GitHub.

To run the application we will have to install the dependencies and update the package.json, here are the commands:

npm install aws-sdk --save

npm install cors --save

npm install express --save
Enter fullscreen mode Exit fullscreen mode

The application can be tested from the local machine by configuring AWS using aws configure and pointing it to your account, and running the Node.js application. This is not covered in the blog (to keep the blog short).

Once the application is tested, the application code can be copied to the EC2 instance by running the scp command. Here are the commands, that I executed to copy the relevant files:

scp -i rsa /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-app/package.json ec2-user@3.235.60.38:/home/ec2-user/api/package.json

scp -i rsa /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-app/index.js ec2-user@3.235.60.38:/home/ec2-user/api/index.js
Enter fullscreen mode Exit fullscreen mode

To run the application on EC2, log in to the EC2 and run npm install to install dependencies, and run the node app (node index.js) to test if the APIs are working.

Ensure that the right ports are opened. I used export PORT=8081, before I run the node index.js and updated my Pulumi code to open that port. Please refer to the latest code on my GitHub.

Now that we have the API running. Let's build a simple React.js application to access this API, and display the results.

ReactJS App

In the ReactJS app, we are building a simple SPA (Single Page Application). You can refer to the complete code on my GitHub. Let's quickly walk you through the application code.

To keep it simple, I am using Material UI (my personal preference is Tailwind CSS).

Line 11–17: In the above code, we are using useEffect() to fetch all the records from DynamoDB, and when the records are fetched, calling the setContacts, to refresh the page to force a render, using useState() hook.

Line 59–73: In the above code, we are defining a JavaScript Method to add a contact. This picks the values provided in the form (the code is below) and calls theaddContact endpoint to add the contact. It then refreshes the page (There are better ways to refresh the page. But to keep the code quick and simple, I am using location.reload(), which is not a good practice. Ideally, we should be using a state)

Line 78–95: In the above code, we are rendering the fetches contacts as a table.

Line 96–115: In the above code, we are rendering a form, that accepts Contact Name and Contact Number, and calls the addContact() method.

To deploy the code, let's copy the React.js code using SCP. The following are the commands, I executed:

scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/src ec2-user@54.85.92.194:/home/ec2-user/contacts-app/src

scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/public ec2-user@54.85.92.194:/home/ec2-user/contacts-app

scp -i rsa -r /Users/vijaykumarab/AB-Home/Developer/contactlist-blog/contactlist-blog-react-app/package.json ec2-user@54.85.92.194:/home/ec2-user/contacts-app
Enter fullscreen mode Exit fullscreen mode

Before we build the application, let's install nvm, pm2 and serve.

Login to EC2.

And execute the following command to install nvm (please refer to the latest documentation on nvm):

curl -o- [https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh](https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh) | bash

. ~/.nvm/nvm.sh
Enter fullscreen mode Exit fullscreen mode

Execute nvm install nodeto install node. To check if the node is installed, run node --version.

To install pm2 and serve execute the following commands:

sudo npm install -g pm2

sudo npm install -g serve
Enter fullscreen mode Exit fullscreen mode

Once all the packages are installed successfully, let's install the application dependencies, and build our React.js app, by executing the following commands:

cd contacts-app

npm install

npm run build
Enter fullscreen mode Exit fullscreen mode

I faced a strange problem when I try to run the npm run build. I was getting Error: error:0308010C:digital envelope routines::unsupported
I found the workdaround from (https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported). Thanks to Peter Mortensen

The above screenshot shows the code compile. Let’s now run the application using pm2, by running the following commands:

pm2 serve build/ 8082 — name “contactlist-app” — spa
Enter fullscreen mode Exit fullscreen mode

To check if our application is running let's run pm2 list.

Let's now go to the browser and check if the application is running. Following is the screenshot I got on my browser:

As you can see, manual deployment is very painful and messy. In the next chapter, we will automate all of this using GitActions and AWS CodeDeploy, so that when we push any changes to the Git (or do pull requests), the code automatically gets deployed.

You can access the complete source code on my GitHub.

You can find the API code (express code) here and ReactJs app code here

Hope this was helpful, let’s meet in the next blog…until then stay safe, and have fun, take care.

Top comments (0)