The MERN stack, comprising MongoDB, Express, React, and Node.js, is one of several technological combinations used for building full-stack web applications. Vercel provides a versatile platform capable of deploying a wide range of frameworks and technologies for various project types. While often associated with frontend hosting, Vercel also supports backend deployments, making it suitable for MERN applications.
This article will guide you through the process of setting up a MERN stack application and deploying it on Vercel. We'll cover the steps from local development to deployment, showing how to utilize Vercel's free tier for testing your project and, if desired, hosting it long-term. By the end of this guide, you'll understand how to leverage the MERN stack and Vercel's deployment capabilities to bring your web application online and make it accessible to users.
Setting up the Development Environment
To beign, you'll need to install the following tools:
-
Node.js and npm
- Visit https://nodejs.org/en/download/package-manager
- Download and install the LTS (Long Term Support) version
- This installation includes npm (Node Package Manager)
-
Visual Studio Code (VS Code):
- Visit https://code.visualstudio.com/download
- Download and install the version appropriate for your operating system
After installation, verify that Node.js and npm are correctly installed by opening a terminal or command prompt and running:
node --version
npm --version
Output>>>>>
Microsoft Windows [Version 10.0.22000.3079]
(c) Microsoft Corporation. All rights reserved.
C:\Windows\system32>node --version
v18.14.2
C:\Windows\system32>npm --version
9.5.0
C:\Windows\system32>
Creating a new React app
- Open your terminal or command prompt
- Navigate to the directory where you want to create your project
- Run the following command:
npm create-react-app client
- Once the installation is complete, navigate into your new project directory:
cd client
- Start the development server to ensure everything is working:
npm start
Your default web browser should open and display the default React app page.
Setting up the Node.js/Express server
- In your terminal. navigate back to your main project directory
- Create a new directory for your server:
mkdir server
cd server
- Initialize a new Node.js project:
npm init -y
- Install the necessary dependencies:
npm i express bodyParser mongodb mongoose cors dotenv
- Create a new file named index.js in the server directory and add the following basic Express server setup:
// index.js
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
app.use("/", (req, res) => {
res.send("Server running.");
});
const port = process.env.PORT || 9000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
- Add a start script to your package.json file in the server directory
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js"
},
- Start your server:
npm start build
Output>>>>>>
PS C:\Users\Matrix\Documents\D.M.F\server> npm start build
> server@1.0.0 start
> nodemon index.js build
[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node index.js build`
Server is running on port 9000
Configuring the Backend
create a new .js file in your backend directory and add the following code:
const mongoose = require('mongoose');
const connectDB = async () => {
try {
await mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
console.log('MongoDB connected successfully');
} catch (error) {
console.error('MongoDB connection error:', error);
process.exit(1);
}
};
module.exports = connectDB;
Setting up MongoDB connection and Creating environment variables
- Log in to your MongoDB Atlas account https://www.mongodb.com/cloud/atlas/register
- Navigate to your cluster's Network Access settings
- Click on "Add IP Address",
- To allow connections from any IP address (suitable for development but should be restricted for production), enter: IP Address: 0.0.0.0/0 Description: Allow access from anywhere
- Click "Confirm".
Important:
Allowing access from 0.0.0.0/0 means your database can be accessed from any IP address. This is convenient for development and testing, but for a production environment, you should restrict access to only the necessary IP addresses or ranges for security reasons.
Create a .env file in your backend directory and add your MongoDB connection string:
MONGODB_URI=your_mongodb_connection_string_here
PORT=9000
Replace your_mongodb_connection_string_here
Structuring the Express app
Now, update index.js
file to incorporate these changes:
require('dotenv').config();
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const connectDB = require('./db');
const app = express();
// Connect to MongoDB
connectDB();
// Middleware
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.json());
// Routes
app.get("/", (req, res) => {
res.send("Server deployed and running on vercel.");
});
// You can add more route files here as your application grows
// app.use('/api/users', require('./routes/users'));
// app.use('/api/posts', require('./routes/posts'));
const port = process.env.PORT || 9000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Developing the Frontend
For the purpose of this article, we'll be using the following structure to illustrate how to organize a React frontend. Keep in mind that React is highly flexible, and you can adapt this organization to best suit your project's specific requirements.
React App Structure
Let's consider the following structure for our React application:
client/
├── src/
│ ├── components/
│ ├── services/
│ ├── styles/
│ ├── App.js
│ └── index.js
├── package.json
└── README.md
- components/: Contains all React components
- services/: Houses API-related code
- styles/: Stores CSS files
Creating Necessary Components
For this project, I've created several key components. Here's an example of one of the main components, UserManagement.js
:
import React, { useEffect, useState } from 'react';
import api from '../services/api';
import IncomingRequestTable from './IncomingRequestTable';
import MembersTable from './MembersTable';
import VolunteerTable from './VolunteerTable';
import './user-management.css';
const UserManagement = () => {
const [showIncomingRequests, setShowIncomingRequests] = useState(true);
const [incomingRequests, setIncomingRequests] = useState([]);
const [teamMembers, setTeamMembers] = useState([]);
const [showVolunteers, setShowVolunteers] = useState(false);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchIncomingRequests();
fetchTeamMembers();
}, []);
// Fetch functions and other logic here...
return (
<div className="user-management-main-container">
{/* Component JSX here... */}
</div>
);
};
export default UserManagement;
This component manages the display of different user tables and handles data fetching.
Implementing API Calls to the Backend
To interact with our backend, I've created an api.js
file in the services folder. Here's a snippet of how it's structured:
const BASE_URL = 'https://localhost:9000';
const handleResponse = async (response) => {
if (!response.ok) {
const error = await response.text();
throw new Error(error);
}
return response.json();
};
const api = {
team: {
getMembers: (status) =>
fetch(`${BASE_URL}/get-team-members?status=${status}`)
.then(handleResponse),
acceptRequest: (userId) =>
fetch(`${BASE_URL}/accept-request/${userId}`, {
method: 'POST',
}).then(handleResponse),
// Other API methods...
},
// Other API categories...
};
export default api;
This centralized API structure allows for easy management of all backend requests.
In the components, we use these API calls like this:
const fetchIncomingRequests = async () => {
try {
const data = await api.team.getMembers('pending');
setIncomingRequests(data);
} catch (error) {
setError('Error fetching incoming requests');
} finally {
setLoading(false);
}
};
This approach keeps our components clean and our API calls organized.
Connecting Frontend and Backend
In this section, we'll focus on configuring CORS (Cross-Origin Resource Sharing) and testing local communication between our React frontend and Express backend.
Configuring CORS
CORS is a crucial security feature that needs to be properly configured to allow our frontend to communicate with the backend. In
index.js
file, we've already set up CORS:
const cors = require('cors');
app.use(cors());
app.use(cors({
origin: 'http://localhost:9000' //to be changed later to vercel url
}));
Testing Local Communication
To test the communication between your frontend and backend locally:
Start your backend server:
npm start build
You should see a message: Server is running on port 9000
In your frontend's api.js file, ensure you're using the correct local URL. For this article:
const BASE_URL = 'http://localhost:9000';
Start your React development server:
npm start
Test an API call, for example, fetching team members:
javascriptCopyconst fetchTeamMembers = async () => {
try {
const response = await fetch(`${BASE_URL}/get-team-members?status=accepted`);
const data = await response.json();
console.log('Team members:', data);
} catch (error) {
console.error('Error fetching team members:', error);
}
};
Check your browser's console and network tab to ensure the request is successful and data is being received.
If you encounter any CORS errors, double-check your CORS configuration in the backend.
Preparing for Deployment
In this section, we'll focus on creating a Vercel configuration file and pushing your code to GitHub repositories, which are crucial steps for deploying your application on Vercel.
Creating a Vercel Configuration File
Vercel uses a configuration file named vercel.json
to specify how to build and deploy your application. Here's the configuration file we'll use:
{
"version": 2,
"builds": [
{
"src": "*.js",
"use": "@vercel/node"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/",
"methods": ["GET","POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
"headers": {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version"
}
}
]
}
This configuration does the following:
- Specifies that we're using version 2 of Vercel's configuration.
- Sets up builds for all JavaScript files using the Node.js runtime.
- Configures routes to handle all HTTP methods and sets up CORS headers.
Create this file in the root of your backend project and name it
vercel.json
.
Pushing Code to GitHub Repositories
Before deploying, you need to push your code to GitHub:
For this project,
create two repositories on GitHub: one for your frontend and one for your backend.
In your backend directory, initialize a Git repository if you haven't already:
git init
- Add your files and commit:
git add .
git commit -m "Initial commit for backend"
- Add your GitHub repository as a remote and push:
git remote add origin https://github.com/your-username/your-backend-repo.git
git branch -M main
git push -u origin main
- Repeat steps 2-4 for your frontend directory, using the frontend GitHub repository URL.
Installing and Using Vercel CLI
To deploy your application using Vercel, you'll need to install and use the Vercel CLI:
Install Vercel CLI globally:
npm install -g vercel
Verify the installation:
`vercel --version`
Log in to your Vercel account:
vercel login
Deploying to Vercel
Before starting, ensure you're logged into your Vercel account.
Deploying the React Frontend
In the Vercel dashboard, click on "Add New"
and select "Project"
from the dropdown.
Choose "Import Git Repository"
and select your frontend repository.
Configure the project:
- Enter a project name
- For Framework Preset, select
"Create React App"
- Set Root Directory to "./" (if your package.json is in the root)
- Leave Build and Output Settings as default
- Leave Environment Variables as default
Click "Deploy"
Vercel will now build and deploy your React frontend. Once complete, you'll receive a URL for your deployed frontend.
Deploying the Node.js Backend
Again, click on "Add New"
and select "Project"
.
Choose "Import Git Repository"
and select your backend repository.
Configure the project:
- Enter a project name
- For Framework Preset, select "Other"
- Set Root Directory to "./" (if your package.json is in the root)
- Leave Build and Output Settings as default
- Configuring
"Environment Variables"
:
Add your environment variables exactly as they appear in your local .env file. For example:
- Key:
MONGODB_URI
- Value:
mongodb+srv://your_username:your_password@your_cluster.mongodb.net/your_database?retryWrites=true&w=majority
Add any other necessary environment variables (e.g., PORT, JWT_SECRET, etc.)
Click "Deploy"
Vercel will begin building your backend code. However, the build may take some time due to environment variables.
You've successfully deployed frontend React App and Backend Node js Server to Vercel!!!
Important Notes:
Make sure your backend code is using environment variables correctly, e.g.,
process.env.MONGODB_URI
.
In your frontend code, update the API base URL to use the deployed backend URL.
If you make changes to your code, push them to GitHub. Vercel will automatically redeploy your application.
Always keep your environment variables secret and never commit them to your repository.
Updating API Endpoints in the Frontend
After successfully deploying both your frontend and backend, you need to update the API endpoints in your frontend code to point to the deployed backend URL.
In your frontend code, locate your API configuration file (e.g.,src/services/api.js
).
Update the BASE_URL to your deployed backend URL:
const BASE_URL = 'http://localhost:9000'; // Local development
const BASE_URL = 'https://dmfc-server.vercel.app'; // Deployed backend
Redeploy your frontend application to Vercel with these changes by pushing to Github.
Final Testing and Verification
Now it's time to thoroughly test your deployed application:
Open your deployed frontend URL in a web browser.
Test all functionalities of your application, ensuring they work as expected with the live backend.
Test your application on different devices and browsers to ensure compatibility.
Monitor your Vercel logs and MongoDB Atlas dashboard for any errors or unexpected behavior.
Conclusion
Congratulations! You've successfully deployed your MERN stack application to Vercel. Here's a summary of what we've accomplished:
- Set up a React frontend and Node.js/Express backend with MongoDB integration.
- Prepared our application for deployment by creating necessary configuration files.
- Deployed both frontend and backend to Vercel.
- Configured environment variables to ensure secure and proper functionality.
- Updated API endpoints and performed final testing.
Your application is now live and accessible to users worldwide
Top comments (0)