The best pattern to set up a server-side for your client-side Application

The best pattern to set up a server-side for your client-side Application

Suppose that you had created the front-end side for one application and after a while, you decide to add a backend server to it. In this article, I will explain that.

Preparing the skeleton

First of all, you need to copy all your front-end code and folders to one folder inside your project and let's call it "client", however, you want to keep the git folder and the .gitignore in the main folder as those have all the history for your commits. After that, we need to create a new package.json file for the server-side. We are simply creating two projects (client + server) in our main application. Also, let's create server.js as this would be the main file for the server-side. In your main folder, you should have a similar form:

image.png

Now it's time to share the package.json and explain it as well.

{
  "name": "name of your app",
  "version": "1.0.0",
  "engines": {
    "node":"your version of node",
    "npm":"your version of npm"
   }
  "scripts": {
    "client": "cd client && npm start",
    "server": "nodemon server.js",
    "build": "cd client && npm run build",
    "dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"",
  },
  "dependencies": {
    "body-parser": "^1.19.0",
    "compression": "1.7.4",
    "cors": "2.8.5",
    "dotenv": "8.2.0",
    "express": "^4.17.1",
  },
  "devDependencies": {
    "concurrently": "^5.3.0",
    "nodemon": "^2.0.6"
  }
}

!! Enter your project name and add the versions of npm and node. To know your version just run node -v or npm -v.

Exemple :

image.png

The dev-dependencies:

nodemon:

This package automatically restarts the node application when the code change. it's just to help you work faster :). For further information visit: https://www.npmjs.com/package/nodemon

concurrently:

We want this package so we can execute two commands at the same time. I mean now you can execute npm start for the client as well as the server with one command and the best of all is that if one of them fails, the other will stop too "--kill-others-on-fail". for further information visit: https://www.npmjs.com/package/concurrently

the dependencies :

body-parser :

It's a body-parser middleware and it parses the body of the upcoming request.

cors:

A library that lets us handle cross-origin requests multiple. For more information visit: https://www.npmjs.com/package/cors

dotenv:

let us store the secret key securely.

express: it is a framework I will use in this example. It gonna make it easier for us to write code.

Building our server

instantiate our framework and all the middleware you will use

const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");

Require dotenv

if you use the .env file to hide your keys we need to config that too.

if (process.env.NODE_ENV != "production") require("dotenv").config();

Basically, we call the dotenv file when we are in development. The config method will load it and return an object with the key parsed. Don't forget to add .env to our .gitignore file.

Create an express application and define your port:

const app = express();
const port = process.env.PORT || 5000;

Add the middleware to your express :

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(cors());

let's explain :

bodyParser.json() returns a middleware to parse JSON. This parser accepts any Unicode encoding of the body.

bodyParser.urlencoded({extended:true}) returns a middleware that only parses {urlencoded} bodies. This parser accepts only UTF-8 encoding of the body. The extended option allows to choose between parsing the URL-encoded data with the query string library (when false) or the qs library (when true). The "extended" syntax allows for rich objects and arrays to be encoded into the URL-encoded format, allowing for a JSON-like experience with URL-encoded.

Cross-Origin Resource Sharing (CORS): basically, cors is a security feature included in all browser it will let resources between two URL of the sea origin and block if it's not. you can find further information at:

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Serving static files in production

//if we are in production
if (process.env.NODE_ENV === "production") {
//use the static middleware to serve the static files:the files in the build folder
  app.use(express.static(path.join(__dirname, "client/build")));
//for any get request we will send in response index.html
  app.get("*", function (req, res) {
    res.sendFile(path.join(__dirname, "client/build", "index.html"));
  });
}

Listen for connection

app.listen(port, (error) => {
  if (error) throw error;
  console.log("server running on port" + port);
});

Last step

Go to the package.json in the client and add a proxy propriety:

  "name": "my app",
  "version": "0.1.0",
  "private": true,
  "proxy":"http://localhost:5000",