How to Deploy a MERN Application on Ubuntu 20.04
The MERN stack consists of MongoDB, Express, React, and Node.js. Together, they allow developers to build applications on the web.
Prerequisites
- Deploy a fresh Ubuntu 20.04 LTS cloud server at Vultr.
- Setup a non-root user with sudo.
- Update your server.
1. Install Node.JS
Install the latest LTS version of Node.js via the NodeSource repository to ensure maximum compatibility with any packages or dependencies in the app.
Import the package signing key.
$ wget -qO- https://deb.nodesource.com/gpgkey/nodesource.gpg.key | sudo apt-key add -
Add the NodeSource repository.
$ echo 'deb https://deb.nodesource.com/node_14.x focal main' | sudo tee -a /etc/apt/sources.list
Update package lists.
$ sudo apt update
Install Node.JS.
$ sudo apt install -y nodejs
2. Install MongoDB
MongoDB is the database that stores all the data for the application. MongoDB also provides a recommended repository for Ubuntu with the latest version.
Import package signing key.
$ wget -qO- https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
Add MongoDB repository.
$ echo 'deb [arch=amd64] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse' | sudo tee -a /etc/apt/sources.list
Update package lists.
$ sudo apt update
Install MongoDB Community Edition.
$ sudo apt install -y mongodb-org
Enable and start MongoDB.
$ sudo systemctl enable --now mongod
3. Setup the NPM Project
Create a new directory for the app.
$ mkdir -p app && cd app
Create a
package.json
file.$ npm init -y
Install the project dependencies: Express web framework, MongoDB driver, React, React DOM, Webpack, Babel, and Dotenv.
$ npm i express mongodb react react-dom webpack webpack-cli html-webpack-plugin @babel/core @babel/preset-env @babel/preset-react babel-loader dotenv
Create directories for the code.
$ mkdir src $ mkdir src/public
Create
src/index.js
, which contains the main server code for Express.$ nano src/index.js
Paste the following:
if (process.env.NODE_ENV !== "production") { require("dotenv").config(); } const path = require("path"); const express = require("express"); const app = express(); const { MongoClient } = require("mongodb"); (async () => { const mongo = new MongoClient(process.env.MONGODB); try { await mongo.connect(); } catch (e) { console.log("Failed connecting to MongoDB"); console.log(e); process.exit(1); } console.log("Connected to MongoDB"); app.use(express.static(path.join(__dirname, "../dist"))); app.listen(process.env.PORT); console.log(`HTTP listening on ${process.env.PORT}`); })();
Save and exit the file.
Create
src/public/App.jsx
, which includes the main code for the React portion of the app.$ nano src/public/App.jsx
Paste the following:
import React from "react"; import ReactDOM from "react-dom"; const App = () => ( <div> <h1>App</h1> </div> ); ReactDOM.render(<App />, document.querySelector("#app"));
Save and exit the file.
Create
src/public/index.html
, which includes the base HTML which the compiled React code will be injected into. It also has the root element that it will render in.$ nano src/public/index.html
Paste the following:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>MERN App</title> </head> <body> <div id="app"></div> </body> </html>
Save and exit the file.
Create
webpack.config.js
, which tells Webpack how to bundle the project.$ nano webpack.config.js
Paste the following:
module.exports = { entry: "./src/public/App.jsx", module: { rules: [ { test: /\.(js|jsx)$/, use: "babel-loader", }, ], }, plugins: [ new (require("html-webpack-plugin"))({ template: "./src/public/index.html", }), ], };
Save and exit the file.
Create
.babelrc
, which configures Babel to compile the React code.$ nano .babelrc
Paste the following:
{ "presets": ["@babel/preset-env", "@babel/preset-react"] }
Save and exit the file.
Create
.env
, which configures the port and MongoDB database URL.$ nano .env
Paste the following:
PORT=8080 MONGODB=mongodb://localhost
Save and exit the file.
Build the app.
$ npx webpack
Start the app.
$ node src/index.js
The app should now be available on port 8080.