Reputation: 129
I've been using Vercel to host several React web applications and it's been great! Recently, I upgraded an existing project with a backend (Express.js and MongoDB Atlas) and I'd like to host it there as well.
On my machine, the MongoDB server and all the CRUD routes are running smoothly on localhost:5000, but I'd like to know how to add this to the Vercel deployment. Vercel's documentation focuses on serverless deployment, and while I don't mind rewriting my backend if I have to, I'm wondering if there's an easier solution for adding a server/database.
The MERN stack is still relatively popular so I imagine a lot of developers have found a way to host this kind of project. If anyone can help, I would really appreciate it!
Upvotes: 3
Views: 8884
Reputation: 225
This repo is setup for MERN stack vercel deployment. I was able to adapt a MERN app and successfully deploy by forking this repo https://github.com/hack4impact-uiuc/mern-template/tree/main/client/src and updating.
Upvotes: 0
Reputation: 1
make sure you have the following in your backend app.js or server.js for the frontend to load on vercelapp/
app.use(express.static(path.join(__dirname, "../frontend/build")));
app.get("*", function(_, res) {
res.sendFile(
path.join(__dirname, "../frontend/build/index.html"),
function (err) {
if(err) {
res.status(500).send(err)
}
}
)
})
Since we are making a rewrite rule: /(.*) vercel will pass all requests through the backend server.js file This snippet will ensure that it sends the build/index.html
Sorry for bad english!
Upvotes: 0
Reputation: 451
according to your comment your file structure should be look like this
// + refer as close folder
// - refer as open folder
// > refer as file
main
- backend
+ models
+ routes
> package.json
> package-lock.json
> server.js
- frontend
+ public
- src
+ pages
+ components
> package.json
> package-lock.json
step1 - edit frontend package.json
add homepage
{
// initially add link whatever you suppose to be link of your site
// then after deploying to vercel, you get the exact link
// then replace it with vercel link in "homepage" key
"homepage": "https://awesome-app.vercel.app",
"name": "awesome-app",
"version": "1.0.0,
"private": true,
...rest of your frontend package.json file
}
step2 - add basename
// you wrapped your app with either BrowserRouter or HashRouter
// add basename prop so it refer to your package.json homepage
// if your route are '/awesome-route' then is converted to
// https://awesome-app.vercel.app/awesome-route
<BrowserRouter basename='/'> // or HashRouter
<Switch>
...your routes
</Switch>
</BrowserRouter>
step3 - build your react
you have to build your frontend everytime before deployment if and only if your change your frontend code
then your frontend should look like below
- frontend
+ build // build folder at root of your frontend
+ public
- src
+ pages
+ components
> package.json
> package-lock.json
step4 - change your server.js file
should look like this
// i use "dotenv" package
// in your case must be located at "main > backend > .env"
// see the final file structure at bottom if you don't understand
if (process.env.NODE_ENV !== 'production') {
require('dotenv').config({path: __dirname+'/.env'});
}
const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const app = express();
app.use(express.json());
const port = process.env.PORT || 5000;
mongoose.connect(process.env.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
// remove poolSize or set according to your need
// read docs before setting poolSize
// default to 5
poolSize: 1
})
.then(() => {
app.listen(port);
})
// all your routes should go here
app.use('/some-route', require(path.join(__dirname, 'api', 'routes', 'route.js'));
// static files (build of your frontend)
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../frontend', 'build')));
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../frontend', 'build', 'index.html'));
})
}
step5 - add vercel.json
at root level of your repository i.e., in your case main
directory
{
"version": 2,
"builds": [
{
"src": "./backend/server.js", // path to your server.js file
"use": "@vercel/node"
},
{
"src": "./frontend/build", // path to your build folder
"use": "@vercel/static"
}
],
// rewrites any request to api call with server.js
// now your "app.use('/some-route')" would work as normal as localhost
// no need to change your codes to serverless way
// also remember here "/(.*)" is not regular js regex
// it follows path-to-regex
// playground link: https://regexr.com
"rewrites": [
{
"source": "/(.*)",
"destination": "/backend/server.js"
}
]
}
finally your file structure look like this
// + refer as close folder
// - refer as open folder
// > refer as file
main
- backend
+ models
- routes
> route.js
> package.json
> package-lock.json
> .env
> server.js
- frontend
- build
+ static
> manifest.json
> index.html
+ public
+ src
> package.json
> package-lock.json
> vercel.json // in your main directory's root
the disadvantage of this method is that your have to build your frontend every time you push your repo to github
remember to build your frontend before you push your repo to github if and only if you change your frontend code
also remember to replace your homepage url in your frontend package.json file after deployment with vercel provided url or your custom domain url
Happy Coding :)
Upvotes: 8