DEV Community

Cover image for How to create a React app with Express from scratch
The Creator
The Creator

Posted on

How to create a React app with Express from scratch

Github Repo: https://github.com/Justinkarso/react-express-starter

Contents

Introduction

Building web apps gives developers the opportunity to reach a wider audience. The combination of Express and React gives developers a powerful tool to create frontends and easily communicate with backends through their own APIs.

React

React Introduction
React is a free and open-source JavaScript library for building user interfaces based on components. It is maintained by Meta and has a large community of developers / companies that improve the overall experience with react. React can be used as a base in the development of single-page or mobile applications, but since the release of some awesome frameworks built on top of react like [NextJS, Remix, Gatsby, etc..] we can now utilize react to create all sorts of apps using SSR, SSG and so forth.

Express

Express Introduction
Express is a minimalist, lightweight framework for making web apps in NodeJS. It is designed for building web applications and APIs. It has been called the de facto standard server framework for NodeJS. One of the major benefits of Express is that developers can use their prior knowledge of JavaScript, without needing to learn a new language.

Prerequisites

To follow along it would be helpful to have the following installed.

  • Node.js installed.
  • A text editor, like VS Code.
  • A web browser, like Chrome or Brave.

You should also know the basics of

  • Javascript / React
  • NodeJS / Express

This guide will not go into detail about these subjects.

Folder structure

Let us create our project. you can name it anything you'd like. I'll name it react-express. Go to any folder where you would like the app to be located at and run the following.

 mkdir react-express
 cd react-express
Enter fullscreen mode Exit fullscreen mode

Great! Now let's immediately create the basic folder structure. In this guide I'll use commands to create folders and files. Afterwards there will be a screenshot.

// dist folder
mkdir dist
cd dist
touch index.html
cd ..

// src folder
mkdir src
cd src
mkdir pages
mkdir styles
touch index.js
cd pages
touch Home.js
cd ..
cd styles
touch global.scss
cd ..
cd ..

// root files
touch .swcrc
touch app.js
touch webpack.config.js
Enter fullscreen mode Exit fullscreen mode

Our folder structure should now look like this.

Folder Structure

Alright, let's not lie about it. You probably don't have a favicon. This is not required but if you want the same one, here you go: https://favicon.io/emoji-favicons/rhinoceros

Installing dependencies

Let's first create our package.json using the init command

npm init -y
Enter fullscreen mode Exit fullscreen mode

Now we are going to install some packages using the following commands:

dependencies

Short ✋

npm i react react-dom react-router-dom express cors concurrently
Enter fullscreen mode Exit fullscreen mode

or

npm install react react-dom react-router-dom
Enter fullscreen mode Exit fullscreen mode

concurrently lets us run multiple commands at the same time

npm install express cors concurrently
Enter fullscreen mode Exit fullscreen mode

dev dependencies

Let's also include nodemon for a better development experience.

We'll also use webpack and include some loaders like sass to use scss in our project and SWC to compile our javascript with the SWC compiler created in rust.

Short ✋

npm i --save-dev @swc/cli @swc/core swc-loader nodemon webpack webpack-cli css-loader sass sass-loader style-loader 
Enter fullscreen mode Exit fullscreen mode

or

Nodemon reruns the express server on every file save.

npm install --save-dev nodemon sass 
Enter fullscreen mode Exit fullscreen mode

Webpack provides a solid bundeling process to build for production as well as making your development experience more fun.

npm install --save-dev webpack webpack-cli
Enter fullscreen mode Exit fullscreen mode

SWC is a Rust based tool that we can use to compile our javascript. There are many more uses for SWC, but we'll only use it here for compiling.

npm install --save-dev @swc/cli @swc/core swc-loader
Enter fullscreen mode Exit fullscreen mode

Add some loaders for webpack to understand our stylesheets

npm install --save-dev css-loader sass-loader style-loader
Enter fullscreen mode Exit fullscreen mode

Scripts

Let's add our scripts inside our package.json.

  "scripts": {
    "build": "NODE_ENV=production webpack",
    "build-dev": "webpack --watch",
    "server": "nodemon app.js",
    "dev": "concurrently \"npm run server\" \"npm run build-dev\""
  },
Enter fullscreen mode Exit fullscreen mode

Setting up React

Now we are ready to populate our files. let's get started by filling in the index.html inside the dist folder.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="icon" type="image/x-icon" href="/favicon.ico" />
    <title>React & Express</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="/bundle.js"></script>
  </body>
</html>

Enter fullscreen mode Exit fullscreen mode

That seems pretty simple doesn't it! We are probably all familiar with this structure while working with react.

Alright so before we are jumping into the express server or configurations, let us populate the src folder first.

src > pages > Home.js

import React, { useEffect, useState } from "react";

export default function Home() {
  const [users, setUsers] = useState([]);
  useEffect(() => {
    const getData = async () => {
      try {
        let response = await fetch("https://jsonplaceholder.typicode.com/users");
        let data = await response.json();
        setUsers(data);
      } catch (err) {
        console.log(err);
      }
    };
    getData();
  }, []);

  return (
    <div className="demo">
      <div className="wrapper">
        <h1>
          A <span>demo</span> showing off <span>React</span> using{" "}
          <em>
            <span>Express</span> | <span>Webpack</span> | <span>SWC</span>
          </em>
        </h1>
        <h2>
          Some Async Data <small>No more extra babel plugins!</small>
        </h2>
        <ul>{users.length > 0 && users.map((user, index) => <li key={index}>{user.name}</li>)}</ul>
      </div>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Wow thats a lot! We are simply creating a Home component that will return some text and fetch some data from jsonplaceholder and displaying it inside a unordered list. bear with me 🐻, we will apply some styling next (even though you can't see it yet..)

src > styles > global.scss

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-size: 14px;
  color: #fff;
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}

.demo {
  background-color: #121212;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2rem;

  .wrapper {
    max-width: 1000px;

    h1,
    span {
      font-size: 4rem;
    }

    h2 {
      margin: 2rem 0;

      small {
        font-size: 0.75rem;
        opacity: 0.5;
      }
    }

    em {
      font-size: 2rem;
      color: #858585;

      span {
        &:first-child {
          color: #ffeb39;
        }
        &:nth-child(2) {
          color: #39ffbd;
        }
        &:last-child {
          color: #d83bd2;
        }
      }
    }

    span {
      &:first-child {
        color: #f44250;
      }
      &:nth-child(2) {
        color: #3992ff;
      }
    }

    ul {
      list-style: none;
      margin-left: 2rem;

      li {
        font-size: 1rem;
        margin-bottom: 1rem;
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

Nice, scss is awesome!

To make your life easier and expand on this project later on, we are going to include react router. Let's do this inside our index.js

src > index.js

import React from "react";
import ReactDOM from "react-dom";
import Home from "./pages/Home";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import "./styles/global.scss";

ReactDOM.render(
  <Router>
    <Routes>
      <Route path="/" element={<Home />} />
    </Routes>
  </Router>,
  document.getElementById("root")
);

Enter fullscreen mode Exit fullscreen mode

As you can see, we're also importing our home component here. We're using the latest version of react router V6, which is a little different from its predecessor.

Phew, that's it for our src folder 😅

General configuration

We now want to add some code to our config files. Don't worry, after this we will create our express server and get things running!

First, navigate to our .swcrc file and add the following

{
  "test": ".*.js$",
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Awesome this lets SWC compile our code to proper javascript that is supported by all browsers!

SWC is 20x faster than Babel on a single thread and 70x faster on four cores.

Check out SWC!

webpack.config.js
now let us populate our webpack.config.js by adding some configuration (duh.. unnecessary sentence).

const path = require("path");
const mode = process.env.NODE_ENV === "production" ? "production" : "development";

module.exports = {
  mode: mode,
  entry: path.resolve(__dirname, "src"),
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: "swc-loader",
        },
      },
      {
        test: /\.s[ac]ss$/i,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
    ],
  },
};
Enter fullscreen mode Exit fullscreen mode

Great, so here we automatically check whether we're in production or development and build instances for those. We also include our SWC and style loaders in the webpack module rules.

Express Server

Cool so we can now finally create our express server! let's open our app.js file and add the following

const express = require("express");
const path = require("path");
const app = express();
const cors = require("cors");

app.use(cors());
app.use(express.json());
app.use(express.static("dist"));

app.get("/*", (req, res) => {
  res.sendFile(path.join(__dirname + "/dist/index.html"));
});

app.listen(3000, () => {
  console.log("App running on http://localhost:3000");
});
Enter fullscreen mode Exit fullscreen mode

Hey that was pretty easy right? We are just telling express to serve our index.html which will render our react app!

Get up and running

Alright so now that we are done creating our code, hurry up and get your app started!

To spin up our development server we'll use:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Yes, it needs to be updated after each change. But there are solutions for that like webpack-dev-server. I didn't include it in this project for personal reasons. But of course you're welcome to add it to your project!

🎉 🎉 Hey check this out! 🎉 🎉

Look at our beautiful webpage.

Getting up and running example 01

To build for production we can simply do

npm run build
Enter fullscreen mode Exit fullscreen mode

Webpack manages the environment for you! You can easily deploy your Node app to any platform like the Digital Ocean App Platform

When you run npm run server our production web app will be deployed on the assigned port, in this case 3000

Conclusion

Alright, so we've built our application using React and Express. Where can we use that?

Well, React has its uses. You can easily create dashboards and advanced web apps that don't rely on good SEO or other marketing strategies. For that approach, you should probably move to NextJS or Gatsby. You can also dive into hydration and server components for react to help with these subjects.

But creating a React app is great. Especially now that our Express server is coming along, we can build full-stack solutions from scratch! There are so many use cases we can handle with this approach.

Please let me know if you've any pointers to improve this post or correct me if I have said something wrong. I'm always open to feedback.

Thank you for reading and Happy Coding 🥷‎‍💻

Top comments (0)