Fullstack JavaScript Microservice Web App in Minutes

Sergey Kravchenko
5 min readMay 27, 2020

--

This article shows how to quickly prototype a web app that consists of the following main architecture components:

  • front-end service: NGINX web server + React.js app.
  • front-end CSS library: Bootstrap.
  • back-end service: Node.js + Express.js.
  • worker service.
  • database: MongoDB.
  • message broker: RabbitMQ.
  • Docker containers.
  • deployment to AWS EC2.

We’re going to use the SMF framework, which helps generate the boilerplate code, connect the services and deploy them to AWS:

https://github.com/krawa76/smf

The demo app code is available here:

https://github.com/krawa76/smf-test-web-app

Requirements: Node.js and Docker with Docker Compose installed locally.

Create project

Install SMF, create a new project and cd to the project directory:

$ npm install -g sokyra-microservice-factory
$ smf new test-app
$ cd test-app

Add back-end service

$ smf add service back-endSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)
prompt: number: 2

Add MongoDB and RabbitMQ services, and the corresponding Node.js client libraries:

0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearch
prompt: number: 3Selected clients:
[MongoDB]
Select another client:
0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearch
prompt: number: 1

Add front-end service

Create the front-end service, point it to the existing back-end one:

$ smf add service front-endSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)
prompt: number: 3Select a back-end service to connect to:
1: demo
2: back-end
prompt: number: 2

Add worker service

Create the worker service, add the RabbitMQ message broker support:

$ smf add service workerSelect service template:
1) Basic worker
2) Back-end (Express.js)
3) Front-end (React.js)
prompt: number: 1==================================================Select third-party services clients that your service "worker" connects to (one at a time),0) exit selection
1) (message broker) RabbitMQ
2) (database) Memcached
3) (database) MongoDB
4) (database) MySQL
5) (database) PostgreSQL
6) (database) Redis
7) (search engine) Elasticsearch
prompt: number: 1

At this point all the boilerplate code modules and config files for the services and Docker stack are ready.

Run app

Let’s start our services and see how they work:

$ smf up

SMF builds Docker images and start containers. When they are running, we can check our web app in a browser:

http://localhost/

http://localhost/kittens

What we see is a React.js / Bootstrap CSS application that receives the data from the back-end service.

We can also check what Docker containers are running behind the scenes:

$ docker ps

Here we see the front-end, back-end, worker, and demo services (added by default and can me removed), as well as MongoDB database and RabbitMQ message broker:

After we’re done with the testing, we can shut down the app (stop the Docker containers):

$ smf down

Project structure

Let’s inspect what we’ve got auto-generated out of the box so far… All the services code lives in one repo:

The other important modules are:

  • smf-stack.json: project config.
  • smf-env.json: environment variables.
  • smf-deploy.json: deployment config.

Back-end structure

The entry point module main.ts does the following:

  • starts the web server.
  • handles the/kittens endpoint.
  • inserts demo data into the database.
  • sends demo messages to the message broker:

Front-end structure

The main modules here are:

  • Dockerfile: builds the service image with NGINX web server embedded.
  • nginx.conf: web server config.
  • ./app folder: React.js application.
  • ./app/src/App.js: main app module with routing.
  • ./app/src/Api.js: API client.
  • ./app/src/pages: Home, Kittens and NotFound pages.
  • ./app/src/components: flash (alerts, errors, etc.) and navigation modules.

Worker structure

The main module shows how to work with shared modules and exchange demo messages with the message broker:

Fetch data from database

So far our back-end API returns the hard-coded demo data, see ./services/back-end/routes/kittens.ts :

Let’s replace this logic with fetching the data from our kittensdb collection:

Start the app again and see the db data on UI:

$ smf up

http://localhost/kittens

Message broker

At this point, the back-end & worker services exchange demo messages using the demo.* RabbitMQ channel. If you need to send some extra asynchronous jobs, you can establish an extra channel:

Develop / debug mode

Back-end: stop the Docker container, prepare SMF debug config:

$ docker stop test-app-back-end
$ smf debug back-end

Then open the project in VSCode and use “Start Debugging” menu (hit F5).

Front-end: start the React app, non-containerized:

$ docker stop test-app-front-end
$ cd services/front-end/app
$ npm start

Deploy

It’s easy to deploy our project to a remote server which has Docker & Docker-Compose installed. If you don’t have one so far, you can create it in Amazon AWS EC2 using the following simple instruction:

https://github.com/krawa76/smf/blob/master/README-provisioner.md

Docker Hub account is also required. You can sign up for free here if it’s missing:

https://hub.docker.com/

Open smf-deploy.json file in the editor and fill in the Docker Hub login/password, host address, and remote machine SSH credentials (ssh key path). Replace the EC2 public host name in BUILD_REACT_APP_API_URL:

Run this command to deploy the project:

$ smf deploy

Ssh to the remote machine and see our microservices running there:

$ ssh -i "/Users/me/.ssh/aws-key.pem" ubuntu@ec2-x-x-x-x.compute1.amazonaws.com$ docker ps
(gives the list of services)

Open the deployed web app in the browser (specify your EC2 host name):

http://ec2-x-x-x-x.compute1.amazonaws.com

Conclusion

Congrats, you have a working prototype of a containerized microservice web app in the cloud!

--

--