Written by Vijit Ail✏️
In modern web development, it’s common to build full-stack applications that consist of a frontend framework, like React, and a backend framework, like Express.js. In this model, React contributes a robust and interactive user interface, while Express handles server-side logic, data storage, and API endpoints.
To efficiently develop and test these applications, it’s essential to run React and Express servers simultaneously. One option is to manually start each server using separate terminal windows or tabs, but this approach is cumbersome and inefficient. An option is to use the concurrently or npm-run-all CLI tools designed to run multiple npm-scripts in parallel or sequentially.
In this article, we’ll explore how to set up and run React and Express together using the concurrently command-line tool to achieve streamlined development workflow, efficient management of frontend-backend integration, and enhanced productivity.
Jump ahead:
- Getting to know concurrently
- Setting up the React frontend
- Setting up the Express.js backend
- Integrating the React component with the API
- Installing and configuring concurrently
Getting to know concurrently
The concurrently command-line tool allows you to run multiple commands or scripts simultaneously from a single terminal window, providing a convenient way to manage and orchestrate different processes within a development environment. concurrently is often used in the context of running React and Express together to streamline the development workflow.
Here’s how concurrently simplifies the development process:
- Single command execution: Allows you to start both the React frontend and Express backend servers with a single command. This simplifies the setup process and saves time and effort
- Streamlined development workflow: Enables automatic restart of both servers whenever changes are made to the frontend or backend code. Eliminating the need to manually stop and restart each server separately provides a seamless development experience and faster iteration
- Consolidated console output: Merges the console output from multiple processes into a single terminal window. Viewing logs, and errors and debugging information from React and Express simultaneously makes it easier to track and debug issues during development
concurrently supports running multiple scripts or commands in parallel. This means you can define separate scripts for starting the React and Express servers in your package.json
file, and concurrently will execute them together.
For example, in your package.json
file, you can define scripts, like so:
"scripts": {
"start:frontend": "react-scripts start",
"start:backend": "node server.js",
"start": "concurrently \"npm run start:frontend\" \"npm run start:backend\""
}
The start
script uses concurrently to execute both the frontend and backend scripts simultaneously. When you run the npm start
command, concurrently will start the React and Express servers, allowing them to work together seamlessly.
Additionally, concurrently provides options to customize behavior, such as controlling the number of processes running simultaneously, specifying custom names for processes, and more. These options allow you to fine-tune the execution of multiple scripts based on your specific requirements.
Setting up the React frontend
To set up the React frontend, open your terminal, navigate to the desired directory for your project, and run the following commands:
> yarn create react-app concurrently-app
> cd concurrently-app
> mkdir server
> touch server/index.js
The above code creates a React app, as well as a server/index.js
file inside the root directory for the backend application.
Setting up the Express.js backend
Next, install the express
and nodemon
packages. Nodemon is a tool that automatically restarts the server whenever changes are made, facilitating a smoother development experience:
> yarn add express
> yarn add -D nodemon
In the server/index.js
file add the following code:
// server/index.js
const express = require("express");
const users = require("./users.json");
const app = express();
const PORT = 3001;
app.get("/api/users", (req, res) => {
return res.json(users);
});
app.listen(PORT, () => console.log(`Listening on port ${PORT}`));
The code sets up an Express server that listens on port 3001
. The server has a single API endpoint, /api/users
, that responds with JSON data from the users.json
file. When a request is made to the /api/users
endpoint, the server sends back the JSON data containing user information.
Integrating the React component with the API
Now let’s have a look at the React component:
// src/App.js
import { useEffect, useState } from "react";
import "./App.css";
function App() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch(`/api/users`)
.then((res) => res.json())
.then((data) => setUsers(data));
}, []);
return (
<div className="App">
<h1>Users</h1>
{users.map((user) => (
<p key={user.id}>{user.name}</p>
))}
</div>
);
}
export default App;
The <App />
component fetches data from the backend, using the fetch
API and the /api/users
endpoint, and then renders the user names received from the backend API. The useEffect
Hook is used to fetch the data when the component mounts. The fetched data is stored in the users
state variable using the useState
Hook.
Now, add the following code to your package.json
file:
// package.json
{
...
"scripts": {
...
"start:frontend": "react-scripts start",
"start:backend": "nodemon server/index.js"
},
"proxy": "http://localhost:3001"
}
The proxy
field specifies the proxy server that will be used in development. It is set to http://localhost:3001
, meaning any API requests made from the React frontend to endpoints starting with /api
will be automatically proxied to the Express backend server running on port 3001
.
Installing and configuring concurrently
It’s time to integrate the concurrently CLI. Begin by installing concurrently as a development dependency in your project. Open your terminal and run the following:
> yarn add -D concurrently
This command installs concurrently and makes it available for use in your project. Next, configure the "scripts"
section of your project’s package.json
file to use concurrently:
"scripts": {
...
"start:frontend": "react-scripts start",
"start:backend": "nodemon server/index.js",
"start": "concurrently \"npm run start:frontend\" \"npm run start:backend\""
},
In the above configuration, the start:frontend
script runs the React frontend using react-scripts start
, and start:backend
script starts the Express backend using nodemon server/index.js
. In the start
script, Concurrently is used to execute both the start:frontend
and start:backend
scripts simultaneously.
After running the npm run start
command in your terminal, you should see the following output: Here’s what you’ll see in the browser: As you can see in the above terminal screen, it can be challenging to identify the source of console output and to distinguish between the frontend and backend processes. The basic configuration serves well for simple setups and fast initiation, but concurrently provides additional customization and flexibility options to enhance the development experience.
To enable a custom configuration, modify the "start"
script according to the following snippet:
"scripts": {
...
"start": "concurrently -n \"FRONTEND,BACKEND\" -c \"red,blue\" -p \"[{name}]\" \"npm run start:frontend\" \"npm run start:backend\""
}
Now, when you run the npm run start
command, you’ll see much clearer identification and differentiation between the frontend and backend processes in the console output: Let’s take a closer look at the command options:
-
-n
: Specifies the names of the processes, in this case,FRONTEND
andBACKEND
are used; allows us to customize the names of the concurrent processes for better clarity in the console output -
-c
: Specifies the colors of the processes, in this case,red
andblue
are used; helps differentiate the console output of the two processes for easier identification -
-p
: Specifies the pattern for the console output, in this case,[{name}]
is used with thename
specified by the-n
option; this pattern helps distinguish the output of each process
The custom configuration provides a foundation for scalability and adaptability. As your application grows, you can easily modify the names, colors, and patterns to accommodate additional concurrent processes or specific requirements. It allows for easy customization based on your project's needs, making it suitable for more advanced or complex applications.
Conclusion
Running React and Express with concurrently greatly simplifies the development process and enhances workflow when building full-stack applications. Developers can use concurrently to seamlessly run both the frontend and backend servers simultaneously from a single terminal window. Whether using a basic configuration or opting for a more customized setup, concurrently offers flexibility and convenience.
Devs can leverage the capabilities of concurrently to effectively construct and test full-stack applications, guaranteeing smooth integration between the React frontend and Express backend. This streamlined approach enhances productivity, enables rapid iteration, and ultimately leads to better DevEx.
Get set up with LogRocket's modern React error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID.
- Install LogRocket via NPM or script tag.
LogRocket.init()
must be called client-side, not server-side.
NPM:
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
Script Tag:
Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
3.(Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- ngrx middleware
- Vuex plugin
Top comments (1)
very insteresting post! but i do have 1 question. is your frontend project folder and backend project folder become 1?