It’s the first time I deployed a full-stack app I created on Render and all seems to be working fine except for the fact that my routes are not found when I reload the component. I’ve got a general idea why as I did a research online but I haven’t managed to solve the problem yet.
Here’s my server file
const express = require("express");
const dotenv = require("dotenv");
const connectDB = require("./config/db");
const path = require("path");
const cors = require("cors");
const corsOptions = {
origin: "*",
credentials: true,
optionSuccessStatus: 200,
};
const app = express();
app.use(cors(corsOptions));
// read variables and save them as environment variables
dotenv.config({path: "./.env"});
// Init Middleware
app.use(express.json({extended: false}));
// data from req object is added to it(middleware)
app.use(express.json());
// Define Routes
app.use("/api/data", require("./routes/data"));
app.use("/api", require("./routes/collection"));
app.use(`/api/item`, require("./routes/item"));
app.use(`/api`, require("./routes/under"));
app.use("/api/users", require("./routes/users"));
app.use("/api/auth", require("./routes/auth"));
app.use("/api/email", require("./routes/email"));
app.use("/api/basket", require("./routes/basket"));
app.use("/api/size", require("./routes/size"));
app.use("/api/wishlist", require("./routes/wishlist"));
app.use("/api/checkout", require("./routes/checkout"));
app.use("/api/payment_confirmation", require("./routes/confirmation"));
const PORT = process.env.PORT || 5000;
// Connect to Database
connectDB();
// Load React App in production
if (process.env.MODE === "production") {
app.use(express.static(path.join(__dirname, "build")));
app.get("*", (req, res) => res.sendFile(path.resolve(__dirname, "build", "index.html")));
} else {
app.get("/", (req, res) => {
res.send("Welcome to the home page");
});
}
app.listen(PORT, () => {
console.log(`App running on port ${PORT}`);
});
That's my package.json and my scripts
“scripts”: {
“start”: “node app.js”,
“server”: “nodemon app.js”,
“client”: “npm start --prefix …/client”,
“client:install”: “npm install --prefix client”,
“build”: “npm install --prefix client && npm run build --prefix client”,
"dev": "concurrently \"npm run server\" \"npm run client\""
}
That's my repo if you want to have a look at the file structure.
enter link description here
enter link description here
I get this error on the console
Error: ENOENT: no such file or directory, stat '/opt/render/project/client/build/index.html'
Although on the events log it says that build is successful so I'm not sure what the correct folder would be.
Thanks in advance
When I downloaded the app and ran it on my system reloading the page, it seems like the server cannot find the routes defined in your server file. This is because your server is configured to handle all routes in your React app's index.html file.
your client-side routes will match the routes defined in your React app, and the server will only serve the index.html file for the initial request.
In your server file, modify your app.get("*")method to serve the index.html file only for the initial request:
if (process.env.MODE === "production") {
app.use(express.static(path.join(__dirname, "build")));
app.get("*", (req, res) => {
// Serve index.html for the initial request
if (req.originalUrl === '/') {
res.sendFile(path.resolve(__dirname, "build", "index.html"));
} else {
// Serve static files for all other requests
res.sendFile(path.join(__dirname, "build", req.originalUrl));
}
});
}
Related
I have created a simple Express JS app. and it is working fine in localhost. when I visit localhost:8000 I see static files (index.html, style.css and frontend.js).
I have tried to deploy that app in a server using cPanel. and I have installed Node app and dependencies using package.json successfully. But when I visit the domain I just see a message (Node JS app is working, Node version is 10.24.1).
How to make my app to point and display the static folder (index.html) and run the app?
My app architecture:
server.js
package.json
public/index.html
public/style.css
public/frontend.js
And here is my server.js startup file:
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');
// Start up an instance of app
const app = express();
/* Dependencies */
const bodyParser = require('body-parser');
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const cors = require('cors');
app.use(cors());
// Initialize the main project folder
app.use(express.static('public'));
// Setup Server
const port = 8000;
const server = app.listen(port, function(){
console.log(`server running on localhost: ${port}`);
});
//POST Route to store data in the app endpoint, projectData object
app.post('/addData', addData);
function addData (req, res){
let data = req.body;
projectData = data;
console.log(projectData);
}
app.get('/getData', getData);
function getData(req, res) {
res.send(projectData);
}
The problem here is that you are not pointing a route to send the HTML file. Otherwise the client would have to point it to the correct path of the file, Like localhost:3000/index.html.
you need to send it from the server using app.get
app.get("/", (req, res) => {
res.sendFile(__dirname + "path to the file");
});
The problem was that I have created the app in a subfolder of my domain.
But when I have created subdomain and reinstalled the app inside it, the app is pointing to static folder successfully.
I'm trying to deploy create-react-app using express.js. I'm also using client side routing (react-router-dom v5) with basename my-app.
When I refresh page the following urls via browser:
https://my-website.com/my-app/
https://my-website.com/my-app/something -> everything works fine.
but when I refresh page with url https://my-website.com/my-app/:type/:id (for example: https://my-website.com/my-app/polar/12345.)
I'm getting following error:
Uncaught SyntaxError: Unexpected token '<' --> browser tries to load /js/chunk.js and /js/main.chunk.js files requesting these urls:
https://my-website.com/my-app/polar/12345/static/js/chunk.js
https://my-website.com/my-app/polar/12345/static/js/main.chunk.js
instead of these:
https://mywebsite.com/my-app/static/js/chunk.js
https://mywebsite.com/my-app/static/js/main.chunk.js . -> Files are located at these urls.
here is my express server file:
const path = require('path');
const express = require('express');
const app = express();
const root = path.join(__dirname, 'build');
app.use(express.static(root));
app.get('/*', (req, res) => {
console.log('requested!', req.originalUrl);
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(9000, () => {
console.log('App is running on port 9000');
});
I'm deploying app via docker file into kubernetes cluster on AWS. Pages are served via nginx ingress controller.
Where should be the problem ?
I am attempting to deploy a Vue.js, Node, Express, MongoDB (MEVN) stack application to Netlify. I successfully deployed the front end of the application to Netlify, and am now attempting to deploy the express server, based on the following serverless-http example: https://github.com/neverendingqs/netlify-express/blob/master/express/server.js
I configured my server to include the serverless-http package:
server.js
const express = require('express');
const app = express();
const serverless = require('serverless-http');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const config = require('./DB.js');
const postRoute = require('./routes');
mongoose.connect(config.DB, { useNewUrlParser: true, useUnifiedTopology: true }).then(
() => { console.log('Database is connected') },
err => { console.log('Can not connect to the database'+ err)}
);
app.use(cors());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use('/messages', postRoute);
app.use('/.netlify/functions/server', router); // path must route to lambda
app.use('/', (req, res) => res.sendFile(path.join(__dirname, '../public/index.html')));
module.exports = app;
module.exports.handler = serverless(app);
routes.js
const express = require('express');
const postRoutes = express.Router();
// Require Post model in our routes module
let Post = require('./post.model');
// Defined store route
postRoutes.route('/add').post(function (req, res) {
let post = new Post(req.body);
post.save()
.then(() => {
res.status(200).json({'business': 'business in added successfully'});
})
.catch(() => {
res.status(400).send("unable to save to database");
});
});
// Defined get data(index or listing) route
postRoutes.route('/').get(function (req, res) {
Post.find(function(err, posts){
if(err){
res.json(err);
}
else {
res.json(posts);
}
});
});
module.exports = postRoutes;
I then re-deployed my application to Netlify, but the server does not seem to run in Netlify. This server is in a folder in project root of my vue.js app. Should I instead run the server as a separate site in Netlify? If not, what should I do in order to get the server to run when deployed in Netlify?
It's been a while, but here goes.
Netlify hosting is for the Jamstack, as they say, i.e. only static files, no processing on the server. The idea is to make use of other mechanisms to get your data dynamically, such as APIs hosted elsewhere, which you query straight from the browser, or when you build your site.
Most likely you actually had to deploy your express.js app as a Netlify Function, instead. Check Netlify's blog post on running express apps on their functions.
I had a similar issue, just that my server wouldn't connect to the routes locally, the major difference between my code and yours was that I had to do
const router = express.Router()
and then switched app.use() with router.use()
Like I said, that's for when the localhost says "cannot GET /* a defined path */"
P.S. As a side note, you don't need explicit bodyParser in recent express, express.json() works fine instead.
When I run my Express.js application with node app.js everything works as expected, including this example route:
router.get('/config/get', function(req, res, next) {
return res.json("hi");
});
However, when I build my docker image and run it, my browsers shows me my index page on this route. In fact, it shows my index page at pretty much every single route, nomatter if I set it up or not. So when I go to /this/route/is/non-existing/ I see my index page as well. This only works through docker. When I visit this page by running the node application without docker, I get a 404.
Be aware that I use connect-history-api-fallback for my vue.js frontend. My app.js looks like this:
require('dotenv').config()
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var history = require('connect-history-api-fallback');
var app = express();
// history mode for making vue.js router work: https://router.vuejs.org/guide/essentials/history-mode.html
app.use(history());
history({
index: '/dist/index.html'
});
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/', indexRouter);
// serving vue.js prod build
app.use(express.static('dist'));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
app.listen(process.env.PORT, () => console.log(`${process.env.NAME} listening on port ${process.env.PORT}!`))
This is my Dockerfile:
FROM node:10
# Create app directory
WORKDIR /usr/src/app
# use non-root user to run commands and give him chown permissions for the directory
USER node
COPY --chown=node:node ./backend .
EXPOSE 8080
CMD [ "node", "app.js" ]
I was building another application in node locally and have now deployed it and am working on another application.
EDIT
However whenever I start node (v5) with express(v4.13) on my localhost it will just hang and not make any connections I am also on a Mac running El Capitan. All that I ever see in the console (By Console I mean the Terminal via Logging) is:
GET / -- ms --
Here is my code below for guidance.
var express = require('express');
var fs = require('fs');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParer = require('body-parser');
var path = require('path');
var app = express();
var settings = app.settings;
var env = process.env;
var entrance = require('./route/siteBase');
app.set('view engine', 'jade');
app.set('view cache', false);
app.set('views', __dirname + '/source');
app.set('/assets', express.static(__dirname + '/source/assets/'));
app.use(logger('dev'));
app.use(cookieParser);
app.get('/', function (req, res) {
res.send('Hello World!');
});
/**
* 404 Error Handler
* Creates an error object to be used and passed to pages.
* TODO move this out of the server.js
* TODO create generic 500/404 page
* NOTE this must always be the last route called (i.e. if the server cannot find any other routes this will be called)
*/
app.use(function(err, req, res, next){
// error page
res.status(500).render('error', {error : err});
});
app.use(function(req, res, next) {
// logic - TODO: Create Error handling here
// console.log(req);
res.status(404).render('error', { error: req.originalUrl });
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
module.exports = app;
please help!
Ok so after a few more hours of debugging the trace led back to some bad NPM package installs which were somehow causing the issue.
I am still not entirely sure what happened, but basically just had to start over from a fresh project and rebuild.
Thank you for the assistance.
The following things you have to keep in your mind.
install dependencies:
$ cd your_app_name && npm install
Install supervisor and use it:
npm install supervisor -g
Edit package.json file and replace below lines :
"scripts": {
"start": "supervisor ./bin/www"
},
run the app with debug mode:
$ DEBUG=your_app_name:* npm start
run app on different port with debug mode:
$ PORT=8080 DEBUG=your_app_name:* npm start
check port is already running or not:
$ netstat -anp tcp | grep 3000
$ sudo netstat -lpn |grep :3000
Kill the running port:
$ sudo fuser -k 3000/tcp
Convert HTML to Jade: here
http://html2jade.aaron-powell.com/
I hope with above information you can sort out your problem.
In express the ordering matters
You have the hello world route after the error and 404 handler.
You need to reorder them.
// even better create a routes file and include it here
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.use(function(req, res, next) {
res.status(404);
res.send('404: Page not found');
});
app.use(function(err, req, res, next){
res.status(500);
res.send('500');
});
Take a look at a express-boilerplate for more details on including routes