I have an elm application running on Heroku.
I didn't want to use a third party elm buildpack, so I compiled the elm files locally and pushed elm.js onto the Heroku server.
My application is using Node.js backend so I'm using this code in expresss to
serve index.html:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (res:any) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
I can go to the heroku URL and everything works perfectly. If I click on the internal /login link, I'm redirected to the login page and my url changes to ww.mywebsite.com/login. Internal routing is not my problem.
This is my problem: Although internal routing works, if I were to manually write www.mywebsite.com/login in the navigation bar, instead of seeing the login page, I see Internal Server Error
How do I fix this? Would I need a heroku buildback to accomplish this?
As #kaskelotti from the comments pointed out, Internal Server Error was printing because the files were being found, but another error was happening once they were found. If the files had not been found I would have received a 404 error.
This was a syntax error in my express code that matched all requests with my static index.html file.
The code posted in my question is wrong, THIS is how it should look:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (req , res) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
The difference is the argument to the callback function in app.get. Originally it was (res) instead of (req, res), so the res variable was mistaken for an object of type Request and not Response, since it was the first argument.
Also as #kaskelotti pointed out, Heroku is irrelevant to this problem.
Related
I have not done this before I tried to see how it is done online but didn't see any reliable method. I keep seeing only the react.js part. I have a Middleware in node.js that returns route does not exist
const notFound = (req, res) => res.status(404).send('Route does not exist')
And I serve it this way in the app.js
app.use(notFoundMiddleware);
app.get('*', (req, res)=>{
res.sendFile(path.join(__dirname, 'build', 'index.html'));
})
This works in postman when I tested an invalid route. However, since I am serving my frontend below it, the code below it doesn't work. If I place the not found middleware below the frontend files, the frontend files would be served but the not found middleware won't work anymore.
How Am I supposed to serve not found middleware and serve it in frontend using react.js?
I have an app.js node main file where I define my api path as the following
app.get('/api/users', UserController.get);
Below in the same file I have the following
app.use(express.static(path.resolve(__dirname, "./front/build")));
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});
The index.html successfully serves React App.
If I open my heroku app somewhere at my-app.herokuapp.com it will open the React app which is intended but the Problem is my-app.herokuapp.com/api/users also serves index.html file instead of JSON that the endpoint is supposed to return.
I tried
I replaced endpoint route definition to come before the "" definition (didn't suffice)
EVEN more, I removed redirection to index.html but heroku still opens the index.html page with any type of request (the "" redirection still works). So, it might have cached something?
Is it about cache (how to clean?) or any other suggestions?
You should create routes and work in a proper flow for each functionality,
For Example:
//app.js
app.use("/api/user",userRoutes);
//UserRoutes
router.post("/signup",UserController.signup);
//UserController
exports.signup = async (req,res,next) => {
//Signup function to add a new user when the user provides required info
}
In this way, you code will be easily accessible and much efficient
The problem appears when after reloading a page, server return only json instead that page
I'm using React and return static files from build folder, there is also express handles routing, it is reproduced only in production mode when running localhost everything ok
app.use('/auth', authRoutes);
app.use('/user', userRoutes);
app.use(['/dota2', '/csgo', '/lol'], generalRoutes);
if (process.env.REACT_APP_ENV === 'production') {
console.log('Production is running');
app.use('/', express.static(path.join(__dirname, '../build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../build', 'index.html'));
});
}
There are routes
const router = Router();
router.get('/live', liveMatches);
router.get('/upcoming', upcomingMatches);
router.get('/past', pastMatches);
router.get('/:matchId', getMatchById);
router.get('/opponents/:tournamentId', opponents);
router.post('/past-team-matches', pastTeamMatches);
You can visit mySite and you will see json as result but if you clear matchId in URL and click on any match the page will load as normal
There is also react-router
<ServiceRoute
key={key}
path={['/dota2', '/csgo', '/lol']}
exact
access
component={Matches}
/>
<ServiceRoute
key={key}
path={['/dota2/:matchId', '/csgo/:matchId', '/lol/:matchId']}
exact
access
component={MatchInfo}
/>
Let's follow the route matching that express does in this case:
When looking for /dota2/566624, it will match here: app.use(['/dota2', '/csgo', '/lol'], generalRoutes); and return the JSON.
When looking for /dota2, it won't match app.use(['/dota2', '/csgo', '/lol'], generalRoutes); so it will continue down until it matches app.get('*', (req, res) => {, serving the React page.
The problem I see here, is that you're using the very same routes for the API and the front-end routing on React. Ideally, when serving the API and the front-end application from the same server you should prefix the API routes, that way they won't clash with the front-end routes. Let's say that you prefix the API routes with: /api. Now you we have:
app.use('/api/auth', authRoutes);
app.use('/api/user', userRoutes);
app.use(['/api/dota2', '/api/csgo', '/api/lol'], generalRoutes);
// ... everything is the same down here
/api/dota2/566624. Will match against the endpoint that returns the JSON on the first load.
/dota2/566624. Will not match the JSON endpoint and will follow down to the '*' route that loads the React app, later, once the app is loaded that route will be handled by the router you're using on the react application.
Don't add the prefix as I did in the example above, use the const router = Router(); you've been using for this purpose as well. I hard-coded the prefix so that I can keep the example short.
One last question is: Why is this not happening on development?
I don't have all the information but for what I can see you're serving the front-end application from a different server than the one running the API; in that case you won't have the route clashing, since they are server from different ports, e.g front-end served on localhost:8080 and API served on localhost:5000.
I hope this helps! please comment if you need info!
:)
i have a nodeJS app on firebase, the front of this app is do with ReactJS.
As long as I do not update the web page everything works perfectly, but if I update, nodeJS takes priority over the url and displays an error because no action is defined for the url
I made a sendFile to the index.html for each url like that :
app.get('*', (req, res) => {
res.sendFile('index.html', {root: `${__dirname}/../public`});
});
Locally, it works perfectly, I can update without losing the page where I am, but when I deploy my application on firebase it does not work. during the update it shows me "not found" and that in the console of the browser
console of the brower
I thought that it could not find the file because firebase arranged them differently but I did not find anything concerning the architecture of firebase :/
I don't know if it's completely clear, I don't know how to explain it better ^^ '
thanks for your time :)
I found!, firebase apparently does not allow the code to leave the function folder (donation impossible to do ../public), so I simply put the public folder in the function folder .
Its gives its:
app.get('*', (req, res) => {
res.sendFile('index.html', {root: `${__dirname}/public`});
});
I am currently trying to learn implementing RESTful APIs using Node.js & Express. Using this tutorial: http://code.runnable.com/U7bnCsACcG8MGzEc/restful-api-with-node-js-express-4
I created each file on my local drive and tried running the code using node server.js..However I kept on getting an error. Why might be causing this?
The code you chose to run is only routing requests for urls that begin with /api as you can see here:
app.use('/api', router);
On top of that, the routes it accepts are /players and /player/:id:
router.get('/players', function(req, res, next) {
res.json({ players: players.getAllPlayer() });
});
router.get('/players/:id', function(req, res, next) {
var player = players.getPlayerById(req.params.id)
res.json(player);
});
For every request, including the routes above, it outputs the method and url to console.log.
Even when it fails to get /, you should see GET / in your console.
Now try to access this url: 0.0.0.0:8080/api/players
It works, right?