I am building an app using node.js + express.js + react.js and I'm using webpack to compile the client side code. The problem I am having is after my client side code is compiled with webpack and I run my app, I cannot refresh the page.
My code:
My webpack compiles my files into /dist/index.html, my app runs on port 3000, and all client side routes are prefixed with /admin.
app.get('/', function(req, res) {
res.render('dist/index.html');
});
When I go to localhost:3000 in the browser and click around the links, the app works fine. However, if I go to, as an example, the about page:
localhost:3000/admin/about
And I refresh, I get the error Cannot GET /admin/about.
I believe the reason is my express router only knows about the / route... so If I refresh directly onto a route like /admin/about, express doesn't know what to render so my solution was to include a "catch all" route:
app.get('*', function(req, res) {
res.render('dist/index.html');
});
However, this keeps giving me the Error: Failed to lookup view "dist/index.html" error.
Can someone help?
Thanks in advance!
After research, I found the solution isn't res.render but res.sendFile:
res.sendFile(path.join(__dirname, '/dist/index.html'));
Related
I have a node js and express server I run on localhost. Recently, while changing the server code from
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
to
app.get('/', (req, res) => {
res.send('home');
});
The server still serves the "index.html" file and does not send the message "home". I also tried deleting all my "app.get()" and "app.post()" functions and it still runs as it was before the changes. I have double checked that I saved the file and restarted the server but even then, still does the same thing. The odd thing is that when changing anything else in the server code aside from my express code it runs as expected.
I tried searching my problem but no one is experiencing the same issues. Any help is appreciated, thanks.
All of your code is not listed, so this is an educated guess, but I would check to see if you are using express.static or another package to serve the directory your index.html file is in via app.use() before your routes. By default express.static will serve index.html if presented a root path ('/').
I was tasked with adding an additional layer of security by adding csrf token. I was able add the csurf package along with cookie parser but I am having issues with react and passing the token to react. I cant post my code here but maybe these specific lines listed below are enough to answer the question.
**//this line here is causing issues because if I remove the get route the index.html will still be servered regardless of whether or not I include the get route request!**
app.use(express.static(path.join(__dirname, 'build')));
//if i comment this get route out the react app is still being served
app.get('/', function(req, res) {
//added this console log to see if this was even being called and it is NOT being called
console.log('get request called');
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
Before I can even get to the csrf token I need to figure out why the get route is not being ran. Question: Why is the react application still being served even if i remove the get route? Is it something with the app.use(express.static...) line?
Yes express.static is serving the index file from your build folder.
https://expressjs.com/en/resources/middleware/serve-static.html
Background
I have a NUXT application that renders vue templates as you would expect. I have a need to hit some Express routes in the application from external applications client side.
I can hit GET routes from external applications but POST requests fail with a error 404.
Example
Express
This works
router.get('/test/get', (req, res, next) => {
res.json({ message: "Global PDF Generator is configured correctly", status: "operational" })
});
This fails with 404
router.post('/test/post', (req, res, next) => {
res.json({ message: "Global PDF Generator is configured correctly", status: "operational" })
});
Inside of the Nuxt application and within any of the vue components I can hit the POST routes like this,
fetch('api/v1/pdf', { method: 'POST' }
But if we try to do something like this it fails,
fetch('localhost:3000/api/v1/pdf', { method: 'POST' }
The second example is important because obvioulsy that is how I would have to hit an end point in this application from an outside application.
What I can not figure out is why the GET requests work and do not get a 404 while the POST requests continue to get a 404 from external applications.
Question
How can I create an externally accessible Express POST end point in my NUXT application so that it will be directly accessible from an external source?
Not as an answer but just so I can format things and demonstrate that something else must be going on. This minimal example works fine for me.
vue init nuxt-community/express-template sample_post
cd sample_post
npm install
Modify api/routes/users.js adding a post route:
router.post('/test', function(req, res, next) {
res.json(message: 'hello');
});
Start up the service:
npm run dev
Verify it returns a post from an external request successfully:
curl -X POST http://localhost:3000/api/test
{"message":"hello"}
So something else must be going on somewhere.
This is because when the NuxtJs app on production it sees only page routes not server route. You should use NuxtJs serverMiddleware. You can find it here from NuxtJs API
I'm using Express and create-react-app.
My React app is a ways along, and now I'm trying to serve it from an Express server.
// server/app.js
const express = require('express');
const path = require('path');
const app = express();
// Serve static assets
app.use(express.static(path.resolve(__dirname, '..', 'build')));
// serve main file
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'build', 'index.html'));
});
module.exports = app;
(My build directory is populated when I do npm run build.
I view the page in Chrome, and what happens when loading the page at localhost:3000 is the Console prints Uncaught SyntaxError: Unexpected Token <, and in the Sources tab it shows that the content of my CSS and JS files are simply the same as index.html: as in this image.
This seems like a recognizable issue, so hopefully someone has seen this before. I'm sort of stumped on where to even begin, especially because I was actually serving the app from Express successfully at first. Then this started happening, then it stopped after some random switching of git branches and reverting and replaying changes, and then it started happening again. So I'm not even sure what makes it happen or not happen.
It appears that your app.use(express.static... call is failing, so instead all of the requests (including for the static assets) are being handled by the app.get('*', (req, res) => { part.
As you are intending to use this to serve a React app, I'd suggest taking inspiration from a boilerplate, "to see how it's done". I personally use NYTimes's kyt project and there's react-starter-kit too.
Try the following code changes which are detailed from the express documentation - serving static files in express:
Replace
app.use(express.static(path.resolve(__dirname, '..', 'build')));
With
app.use(express.static('build'))
Remove
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'build', 'index.html'));
});
The problem was "homepage": ... in package.json.
When npm run build runs and there is a homepage URL in package.json that has a non-empty path (like a Github Pages URL like this, https://username.github.io/project_name, where "/project_name" is the path), it changes where it expects the files inside /build to be. The requests for my js and css were going to /project_name/static/... instead of /static/....
It even said in the log output of npm run build:
The project was built assuming it is hosted at /project_name/.
You can control this with the homepage field in your package.json.
On my localhost, it wasn't hosted at /project_name/, so the paths were off.
I've scaffolded a full stack Mongo, Express, Angular, Node app using yeoman with the Angular Fullstack generator
It has created a server/app.js file, which executes a routes.js to handle resources being served by the express server.
The meat of routes.js looks like this:
// Insert routes below
app.use('/api/things', require('./api/thing'));
app.use('/api/users', require('./api/user'));
app.use('/auth', require('./auth'));
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
// All other routes should redirect to the index.html
app.route('/*')
.get(function(req, res) {
res.sendfile(app.get('appPath') + '/index.html');
});
My question is how any file other than index.html gets served to the browser. I've tested, and for example the file "http://localhost:9000/assets/images/yeoman.png" does get returned to the browser. But how? From what I am reading in the routes.js, a request to that png should return the text of index.html
I'm a bit confused by this and would really appreciate an explanation.
Thanks!
If you go into config/express.js you will see something like this:
app.use(express.static(path.join(config.root, 'public')));
Which should be self-explanatory.
UPD. With routes you can overwrite this behaviour for specific files (if you really need it).