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

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.

Related

The edit I made on my react component does not reflect after being served with express

I served my react app with an express server every thing worked fine on my local host , but all other edit I made on the react components does not reflect it keeps showing the old data , i thought it was a cache issue i cleared my cache but nothing worked, i deleted everything and started again it still happened
this is my code in my express server
var express = require("express")
const app = express();
const path = require('path')
const reactBuild = path.join(__dirname, 'client', 'build')
app.use(express.static(reactBuild))
app.get("/api", (req, res) => {
res.send("the api")
})
app.get("*", (req, res) =>{
res.sendFile(path.join(reactBuild, 'index.html'))
});
app.listen(5001, () => {
console.log("listening on port 5001")
});
i cross checked the pathing everything it's well pathed the build folder is inside the react folder
this is the file path
file structure
The edit I Made:
the components i edited and added
it keeps sending old data
old data

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);
});

How do I rewrite all urls to index.html in Heroku?

My Heroku app is using React with React Router. I use Switch to navigate through different components, so the URL changes as well (e.g. /room/4141). However, if I reload the page, it doesn't act like if it was a React app, but instead it searches for the mentioned .html file.
I used this Buildpack: https://github.com/mars/create-react-app-buildpack.git but it seems to do nothing in regards with pages being rewritten to index.html.
Is there a way to prevent this behaviour and rewrite all URLs to index.html?
**EDIT:
I'm not familiar enough with express, but here's how the index.html is served.
const express = require("../../node_modules/express");
const app = express();
const server = require("http").Server(app);
const io = module.exports.io = require('../../node_modules/socket.io/lib')(server)
const path = require("path")
app.use(express.static(path.join(__dirname, '../../build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../../build')));
console.log("DEBUG HERE", __dirname, path.join(__dirname+'../../build'));
//
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../build/index.html'));
})
}
//build mode
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../public/index.html'));
})
That buildpack can be configured via a JSON file:
You can configure different options for your static application by writing a static.json in the root folder of your application.
One of the sample routing configurations looks like it does exactly what you want:
When serving a single page app, it's useful to support wildcard URLs that serves the index.html file, while also continuing to serve JS and CSS files correctly. Route ordering allows you to do both:
{
"routes": {
"/assets/*": "/assets/",
"/**": "index.html"
}
}

expressJWT blocking public folder, how to unblock?

my express/node backend app and frontend app used to be separated, the backend run on localhost:3000 and the front end app was started with ng serve and run on localhost:4200
However after I builded the app, and all the frontend stuff got minified and put in /public/ folder, they both run on port 3000. I'm pretty sure they are supposed to work like that. Since i'm using expressJWT middleware to protect some of my routes for visitors without a token, i'm now getting unauthorized 401 when trying to receive the frontend app in the browser.....
As the image shows, i can aparently load the index.html without problems, i can also load all the external hosted sources like boots strap and jquery etc...
but my own .js files is 401. I think it is because of the expressJWT, but i'm not entirely sure. Does anyone know what the problem is and how to solve it ?
It could also be express that is wrong configured?
as you can see i have tried to "ubnlock" the public folder like so:
app.use(expressJWT({secret: secret}).unless({path :
['/','../public/*','/api/authenticate', '/api/register']}))
full express:
const express = require("express")
const bodyParser = require("body-parser")
const logger = require('morgan')
const api = require("./api/api")
const path = require('path')
const secret = require('./models/secrets')
const expressJWT = require('express-jwt')
const cors = require('cors');
const app = express()
app.set("json spaces", 2)
app.use(logger("dev"))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
// CORS middleware
app.use(cors());
app.use(expressJWT({secret: secret}).unless({path : ['/','../public/*','/api/authenticate', '/api/register']}))
app.use("/api/", api)
app.get('*', (req,res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
app.use(function (req, res, next) {
var err = new Error('Not Found')
err.status = 404
next(err)
})
app.use(function (err, req, res, next) {
console.error(err.status)
res.status(err.status || 500)
res.json({ msg: err.message, status: err.status })
})
// Body Parser middleware
app.use(bodyParser.json());
// Set static folder
app.use(express.static(path.join(__dirname, 'public')));
//Call this to initialize mongoose
function initMongoose(dbConnection) {
require("./db/mongooseConnect")(dbConnection)
}
app.initMongoose = initMongoose
module.exports = app
use express static middleware before using jwt.
example:
app
.use(express.static(STATIC_PATH))
.use(
exjwt({ secret: SECRET }).unless({
path: [/\/api\/v1\/identify/]
})
)
I am not 100% sure but I guess you have problem with this line.
app.use(expressJWT({secret: secret}).unless({path : ['/','../public/*','/api/authenticate', '/api/register']}))
app.use("/api/", api)`
Try this. putting single / should solve.
app.use('/api',expressJwt({secret: secret}).unless({path: ['/','/public/*','/api/authenticate', '/api/register']});

Rendering AngularJS HTML page on server side NodeJS

I have NodeJS server + AnglarJS page.
All works.
Do working examples or frameworks that allow the download page on the server NodeJS and fill it and return to the client a static page. It is necessary for Browsers IE 5-8 (90% clients).
Yes, take a look at Express for Node.js - you can easily serve up a single static page and then use a link to redirect users to your Angular app (using a 'login' page, for example).
Here is an example of a very basic Express app.
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
var server = app.listen(3000, function () {
var host = server.address().address
var port = server.address().port
console.log('Example app listening at http://%s:%s', host, port)
})
The req (request) and res (response) are the exact same objects that Node provides, so you can invoke req.pipe(), req.on('data', callback) and anything else you would do without Express involved.
The app starts a server and listens on port 3000 for connection. It will respond with "Hello World!" for requests to the homepage. For every other path, it will respond with a 404 Not Found.
Save the code in a file named app.js and run it with the following command.
$ node app.js
Then, load http://localhost:3000/ in a browser to see the output.

Resources