Express React Router and Middleware - reactjs

I have a server/website that is using express and react. I'd like to serve the website using app.use(express.static()). This is working the way I'd like to except it is interfering with a single server handled url /parse-dashboard which is served as a separate middleware.
const path = require( 'path' )
var express = require('express');
var bodyParser = require('body-parser');
var basicAuth = require('express-basic-auth');
var ParseServer = require('parse-server').ParseServer;
var ParseDashboard = require('parse-dashboard');
var url = require('url');
var app = express();
var config = require( path.join( __dirname, 'config' ) )
app.use('/parse-dashboard', ParseDashboard(config.dashboard, true));
// Middleware for reading request body
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, './client/build')));
app.set( 'port', process.env.PORT || 3000 )
const server = require( 'http' ).createServer( app )
server.listen( app.get( 'port' ), () => {
console.log('express server listening on port ' + ( process.env.PORT || server.address().port ));
});
When I go to /parse-dashboard, the React app (which is using react-router-dom) takes the url and shows a blank route. How can I have this route be shown by the server instead?

I figured it out and boy do I feel dumb. In the React app folder contained inside my server(Express) folder I have a package.json file to declare the React dependencies. The package.json file still had the proxy key contained in it that some guides have mentioned to use in order to get api calls to your own server to go through when working locally. After removing that key it all works as expected, /parse-dashboard is handled by express and the rest are handled by react-router-dom

Related

React-router urls don't work when refreshing or writing manually, gives 404 page not found

My production webiste opens normally, but for a user visiting/accessing that link the first time, he gets a 404 Page Not Found. For users that has already visited the website it loads just fine.
This is the url - https://literacycloud.org/readaloudsdetail/546-jennifer-phillips-reads-the-invitation.
Ideally it should redirect to the login page, but there is no api being hit at all.
The issue doesn't get reproduced locally only when deployed to development or to live, getting this issue.
Is it something back-end has to handle from their end?
Any help appreciated.
Set historyApiFallback in your webpack.config.js. Checkout this.
Also, it is a good idea to serve your index.html from a server. The idea is that no matter what url you visit on your domain, the server should always return the index.html as it contains your react code.
Here is a sample code:
const path = require('path');
const express = require('express');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
app.set('port', process.env.PORT || 8080);
app.get("*", (req, res, next) => {
const filePath = path.join(__dirname, 'build', 'index.html');
res.sendFile(filePath);
});
const server = app.listen(app.get('port'), function () {
console.log('listening on port ', server.address().port);
});

Prerender.io with reactjs/express application not recognizing Prerender token

I'm trying to get prerender set up with my application. I'm using react on the client side, and express on the server side. I set up an account on prerender IO, and have installed the prerender-node middleware as recommended by the site. Here is what my server looks like:
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
const SocketManager = require('./sockets/SocketManager')
const path = require('path');
const users = require("./routes/api/users");
const queries = require('./routes/api/queries');
const forumActions = require('./routes/api/forumActions');
// Routes
app.use("/api/users", users);
app.use("/api/queries", queries);
app.use("/api/forumActions", forumActions);
// Serve static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
app.use(require('prerender-node').set('prerenderToken', 'xxxTOKEN_CODExxx'));
const port = process.env.PORT || 80;
const server = app.listen(port, () => console.log(`Server running on port ${port} !`));
const io = require('socket.io')(server);
io.on('connection', SocketManager);
On the client side I'm using react-helmet to dynamically render the meta tags (title, description, etc.) based on the route. Ideally I would like to be able to share posts on social media and have the meta data display (which to my understanding prerender can do by prerendering pages specifically for web crawlers).
I've set up a prerender.io account and added my URL to the cached pages, but for some reason I am getting a message saying "We haven't seen a request with your Prerender token yet.". I am hosting on heroku, and have tried adding the token using the heroku CLI, which still hasn't fixed the issue.
Is there a step I'm missing, or did I not set this up correctly? Thanks!
It looks like you might need to move the prerender-node middleware higher up in your file so that it executes just after your routes but before the index file is served back.
Then you can change your user agent in your browser to Googlebot and visit your URL. If the middleware is set up properly, you would see a prerendered response and a request in your Prerender.io Crawl Stats.

MEAN application setup doesn't redirect routes to Angular application

I am trying to setup a base for a MEAN application. I created the new project using Angular CLI, added Express.js, MongoDB modules to the application. In the app.js file I have the following configuration:
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var path = require("path")
var app = express();
var conf = require('./config/conf');
var server = require('http').Server(app);
var mongoDB = require('./adapters/mongodb')
var mongoClient = new mongoDB(conf);
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,__setXHR_');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
mongoClient.connect(function (dbconn) {
app.dbconn = dbconn;
app.conf = conf;
console.log("************************************************************");
console.log(new Date() + ' | CRUD Server Listening on ' + conf['web']['port']);
console.log("************************************************************");
server.listen(conf['web']['port']);
var Routes = require('./routes/http-routes');
new Routes(app);
});
I setup a hello world route for now and no changes done to the angular sources, which means I would land at the Angular default starting page. But I cant land at the page but instead a white screen page. However, I can access the routes using Postman. I do ng build and then node app.js to run the application. What am I doing wrong?
You should use the Express way to handle routes
First
const router=express.Router();
Then let's suppose you have a file using only authentication routes
const authentication = require('./routes/authentication')(router);
To conclude, you only have to do :
app.use('/authentication', authentication);
This allows a better divison of your routes
You 'll use your routes this way
module.exports= (router)=>{
router.get('/',(req,res)=>{
res.json(message:'Hello World');
});
return router;
To set angular routes you need the router module, for more details read the documentation
You serve only index.html from your Angular App. But you need also serve assets, css and javascript. Easiest would be something like this (but you need to adjust directory names:
app.use('/js', express.static(path.resolve(__dirname, 'dist/js')));
app.use('/css', express.static(path.resolve(__dirname, 'dist/css')));
app.use('/assets', express.static(path.resolve(__dirname, 'dist/assets')));

How can I get livereload working for my express app?

Currently running an angular+express app. Trying to implement a livereload but without success. This is the server.js:
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
var livereload = require('livereload')
livereload = require('livereload');
server = livereload.createServer();
server.watch(__dirname + "/scripts");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/scripts'));
app.get("/hello", function(req, res) {
console.log('api hello');
res.send("Hello worldjjjjhjhjh");
});
var server =app.listen(3000,function(){
console.log('listening on port ',server.address().port);
});
The app runs fine but when I change the angular code there is no reload , the browser does not reload? This is the link to github, checkout the livereload branch: https://github.com/dimitri-a/simpleng/tree/livereload.
check if the application does not run on production mode, that worked for me.

GET error MEAN App

I've been learning how to use the MEAN stack in order to build web apps and so far it's been a lot of fun. Instead of using yeoman generators or npm app to generate my code for me, I've been building my whole app from the ground up. This way I know how each piece connects and what is going on with my app. I was just starting to connect the front and back end of my app when I looked at the developer console and saw
GET http://blog.dev/bower_components/angular/angular.js
Not only angular, but every other resource I have (Modernizr, angular-routes, mootools, restangular, etc ...). When you use the yeoman angular generator you are suppose to run the grunt serve command to start up the angular side. Because I built the app from scratch and I am using npm for my build tool I didn't know how to build the front end server. So, I just went with a simple nginx virtual host pointing to my index.html. Here's the config:
server {
listen 80;
server_name blog.dev;
root /home/michael/Workspace/blog/app;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
I'm not sure what other variables could be affecting the situation, so if I missed something please tell me and I'll be happy to give you what you need!
If you're using the mean stack, you should be able to host both the back end and serve the front end directly with node.
I'm not sure of your project structure but here's the structure for one I'm working on now.
/bin --contains a file called www.js (used to launch app)
/data
/models
/node_modules
/public -- contains my angular implementation
/routes -- contains express routes
/temp
/upload
/views
app.js -- main configuration for express
api.js -- my apis
package.json
in the /bin/www.js file you have the code to start your node server.
var app = require('../app');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
You'll also need to setup express and your routes so well look at routes first
in the routes directory I have a file called index.js
In this file, I define one route that leads to my angular index.html page.
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.redirect('/pages/index.html');
});
module.exports = router;
And of course you'll need to set up express.
process.env.TMPDIR = 'tmp'; // to avoid the EXDEV rename error, see http://stackoverflow.com/q/21071303/76173
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var multer = require('multer');
var flow = require('./flow-node.js')('tmp');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
var uuid = require('uuid');
var mongoose = require('mongoose');
var session = require('express-session');
var routes = require('./routes/index');
var app = express();
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(session({genid: function(req) { return uuid.v4()}, secret: 'XXXXXXXXXXX',
saveUninitialized: true,
resave: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
module.exports = app;
Now assuming you have your Angular files and javascript in the 'public' directory somewhere, you should be able to start up Node with the following command.
node bin/www
And the point your browser at http://localhost:3000 and be in business.
Hope this helps and happy learning.

Resources