How to connect Express backend and Next.js frontend? - node.js

I modified my server.js(by looking at Vercel site)
connectDB();
const routes = require('./routes');
const blogpost = require('./routes/blogpost');
const auth = require('./routes/auth');
const users = require('./routes/users');
const comments = require('./routes/comments');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare()
.then(() => {
const server = express();
server.use(handler);
server.use(express.json());
server.use(cookieParser());
server.use(mongoSanitize());
server.use(helmet());
server.use(xss());
if (process.env.NODE_ENV === 'development') {
server.use(morgan('dev'));
}
const limiter = rateLimit({
windowMs: 10 * 60 * 1000,
max: 100,
});
server.use(limiter);
server.use(hpp());
server.use(cors());
server.use('/api/v1/auth', auth);
server.use('/api/v1/blogpost', blogpost);
server.use('/api/v1/users', users);
server.use('/api/v1/comments', comments);
const PORT = process.env.PORT || 5000;
server.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`));
});
Backend and frontend are separate folders,so I figured out that concurrently help me solve this.
My package.json
"scripts": {
"start": "node server",
"client": "cd ..//frontend && npm run dev",
"server": "nodemon server",
"dev": "concurrently --kill-others-on-fail \"npm run client\" \"npm run server\"",
"test": "jest"
},
I got error
internal/modules/cjs/loader.js:1083
[1] throw err;
[1] ^
[1]
[1] Error: Cannot find module 'react'
[1] Require stack:
[1] - /home/jholmes/blog_mongo/backend/node_modules/next/dist/next-server/server/render.js
[1] - /home/jholmes/blog_mongo/backend/node_modules/next/dist/next-server/server/nextserver.js
[nodemon] app crashed - waiting for file changes before starting...
[0] ready - started server on http://localhost:3000
[0] event - compiled successfully
I can signup at the frontend but no data is passed to the backend.
What is wrong with my configuration?

From your explanation and package.json file, it seems you were creating a microservices application where the backend standalone from the frontend.
But your server.js file shows that you were creating a monolithic application where the frontend and backend is on the same instance.
The error message explains that to do Server Side Rendering (SSR), it needs reactjs library to render the frontend, unfortunately couldn't find reactjs because your backend supposed to not having reactjs.
If you want to create microservices application, then the way frontend connect to backend is via APIs. If you tend to have monolithic application, then you need to read the SSR documentation of NextJS.

Related

How to properly configure Next.js as a frontend and Express app as a backend?

Currently I have create-react-app for frontend and express server for backend. In package.json of my create-react-app I use proxy like this "proxy": "http://localhost:5000".
I need to achive the same thing for Next.js app with the same express server.
I just want to be able to use my express server instead of API routes built in Next.js and proxy it like I do in create-react-app.
Do I need to create custom Next.js server even though i'm not changing any of it's functionality? How to do this properly?
yes you have to add custom server in next js
install express js then add file server.js in root directory of next js project
const express = require('express')
const next = require('next')
const bodyParser = require('body-parser')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.use(bodyParser.json())
// add custom path here
// server.post('/request/custom', custom);
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('Ready on http://localhost:5000')
})
})
after that change package.json file script section
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js",
}

How to Setup Proxy Target in React Native with Nodejs?

Trying to configure proxy in react native with node to run axios calls.
Tried the following code in server/package.json
"proxy": {
"/*": {
"target": "http://localhost:5000/"
}
},
"scripts": {
"start": "node index.js",
"server": "nodemon index.js",
"client": "cd ../client && yarn ios",
"dev": "concurrently \"yarn server\" \"yarn client\""
}
server/authRouter.js
const authRouter = require('express').Router();
authRouter.get('/test', (req, res) => {
res.send('proxy success');
});
module.exports = authRouter;
server/index.js
const express = require('express');
const authRouter = require('./authRouter');
const app = express();
app.use('/auth', authRouter);
const PORT = process.env.PORT || 5000;
app.listen(PORT);
client/app.js
await axios.get('/auth/test');
When I run yarn dev and test an axios call, it logs the following error
LOG [Error: Network Error]
any help would be much appreciated.
Try calling the proxy directly in axios
http://localhost:5000/auth/test
I'm not sure why it doesn't work that way, even i had a problem in the past.

Problem when Client (react) and Server(nodejs) are in the same folder

I'm trying to deploy my web application, that has my client and server at the same main folder, to Heroku and I face some annoying problem that the server isn't serving the react build folder.
Here's my project folder tree:
/client
/api
app.js
server.js
app.js => routes, loading models, controllers, etc
server.js => server configuration
Here's the content of server.js, I believe the problem is here
const app = require('./app');
const path = require('path');
const cors = require('cors');
const express = require('express');
app.use(cors())
if (process.env.NODE_ENV === "production") {
console.log('we are on production!')
app.use(express.static('./client/build'));
app.get('*', (req, res) => {
console.log('redirecting to react app build')
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"))
});
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on PORT ${port}`))
It never gets to the console.log('redirecting to the react app build') part
When I entered my heroku server I face the server side instead of my react build. why is that so?
I've just created a test project using your architecture. My project is running and uploaded on Heroku right now. I'm gonna detail all steps I just do to make it works according to given information.
So my project architecture :
client/ // from CRA
package.json
server.js
.env
Configure your environment variable :
heroku config:set NODE_ENV=production // this for production heroku
In my .env file I set local environment variables such as :
NODE_ENV=production
Here's my main package.json file which I defined a heroku-postbuild to create the client build folder.
{
"name": "foo",
"version": "1.0.0",
"main": "index.js",
"license": "mit",
"dependencies": {
"cors": "2.8.5",
"express": "4.17.1",
"path": "0.12.7"
},
"scripts": {
"start": "node server.js",
"heroku-postbuild": "cd client && yarn && yarn build"
}
}
And the server.js file, almost the same as the one provided
const path = require('path');
const cors = require('cors');
const express = require('express');
const app = express()
app.use(cors())
if (process.env.NODE_ENV === "production") {
console.log('we are on production!')
app.use(express.static('client/build'));
app.get('*', (req, res) => {
console.log('redirecting to react app build')
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"))
});
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on PORT ${port}`))
You can run Heroku in local by typing this command heroku local in will loaded the .env file with environment variables.
To test production Heroku you have to type heroku open. Don't forget to set up "production" environment variable with command I wrote above.
Everything's working fine. I can upload my code to Github if you want me to.

Deploy React App to heroku cannot connect backend

I am trying to deploy my app which using node.js, react and MongoDB to Heroku; The deploy was succeeded; However, the website cannot fetch data from MongoDB.
The error is GET http://localhost:5000/comment net::ERR_CONNECTION_REFUSED and Uncaught (in promise) Error: Network Error, I think it is because I don't have node server.js running in the backend. can anyone help me with how to deploy this correctly?
my pakage.json in the backend is
"client-install": "npm install --prefix myprofile",
"start":"node server.js",
"server":"nodemon server.js",
"client":"npm start --prefix myprofile",
"dev":"concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild":"NPM_CONFIG_PRODUCTION=false npm install --prefix myprofile && npm run build --prefix myprofile"
}
And my server.js is
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const path = require("path");
require("dotenv").config();
const app = express();
const port = process.env.PORT || 5000;
app.use(express.json());
app.use(cors());
//app.use(express.static(path.join(__dirname,'./myprofile/build')));
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
});
const connection = mongoose.connection;
connection.once("open", () => {
console.log("MongoDB data connected");
});
const CommentRouter = require("./CommentRouter");
app.use("/comment", CommentRouter);
if (process.env.NODE_ENV === "production") {
app.use(express.static("myprofile/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "myprofile", "build", "index.html"));
});
}
app.listen(port, () => console.log(`Server is running on ${port}`));
Thank you very much in advance!
If you are deploying this project to heroku, your start command and your server.js looks similar to this example so that's a good start.
Are you setting your environment variables with heroku, specifically process.env.ATLAS_URI? I would imagine heroku doesn't know where your MongoDB database is located.

React content not found heroku deployment

Im trying to deploy a nodejs and react app to Heroku. It works completely fine local and it does serve my backend, but i get Not Found on anything else than my api endpoints. It seems like its not running the build script in the client folder. Can anyone help me spot where it goes wrong?
server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const path = require('path');
const projects = require('./routes/api/projects');
const app = express();
// Body parser middlewaree
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to DB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('mongoDB connected.'))
.catch(err => console.log(err));
// Setting up routes
app.use('/api/projects', projects);
// Serve static assets if in production
app.use(express.static(path.join(__dirname, '/client/build')));
app.get('*', (req, res) => {
res.sendfile(path.join((__dirname, '/client/build/index.html')));
});
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server up and running on ${port}`));
package.json
"scripts": {
"client-install": "npm install --prefix client",
"start": "node server.js",
"server": "nodemon server.js",
"client": "npm start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
},
I've deployed successfully to Heroku using the following code (I've just answered an alike question here):
app.use(express.static(path.join(__dirname, './client/build')))
app.get('*', function(_, res) {
res.sendFile(path.join(__dirname, './client/build/index.html'), function(err) {
if (err) {
res.status(500).send(err)
}
})
})
Also, if you're trying to deploy a create-react-app application, you can use this buildpack. Buildpacks are scripts that are run when your app is deployed. They are used to install dependencies for your app and configure your environment.
You can see the full code here of how I usually deploy Heroku applications.

Resources