prerender / prerender-node

Express middleware for prerendering javascript-rendered pages on the fly for SEO
914 stars 181 forks source link

prerender-node using Firebase cloud functions #146

Closed tonyj-dev closed 7 years ago

tonyj-dev commented 7 years ago

Hi, I'm trying to use prerender-node using an Express app running in Firebase cloud functions. As per your documentation I did the following:

const express = require("express") const app = express() app.use(require('prerender-node').set('prerenderToken', '****TOKEN****'))

app.get("*", (req, res) => { console.log('fired express app') res.status(200).end() })

exports.prerender = functions.https.onRequest(app);

When /prerender is executed, it runs the express app - but when we check the console on prerender.io - nothing is invoked. I think we might be missing a step in the execution?

thoop commented 7 years ago

Hi @jreijt. Did you try accessing a URL that would be matched by the middleware? Try a URL with ?_escaped_fragment_= on the end of the URL or try sending a request with a user agent of facebookexternalhit.

tonyj-dev commented 7 years ago

Yes we did try adding _escaped_fragment_= but still nothing shows on the prerender.io dashboard and the page doesn't load like it should. It's worth mentioning that the URL for the cloud functions that runs prerender-node isn't the same one as the URL of the page to prerender - so is there some way to reference a different URL? How do you think this could be achieved?

thoop commented 7 years ago

The prerender-node middleware has to run within the same request lifecycle as the URL being accessed by the crawler so I don't think this set up will work correctly. Are you able to modify things to get it to run within the same request lifecycle?

tonyj-dev commented 7 years ago

Unfortunately this doesn't seem possible with Firebase cloud functions. Routes that are reserved for our Angular app get completely overridden if we apply a cloud function on that route. I've requested google support on the matter to figure out how to render a page while running a cloud function, but this doesn't seem possible with their current version.

thoop commented 7 years ago

Ah, ok. Please let me know if you're able to get it working!

vinicius91carvalho commented 6 years ago

First of all, sorry for my poor English.

After searching through Deep Web (joking), I found the solution. And the coolest solution was that I was able to integrate my Pioneer Ionic application with Firebase Hosting using Cloud Functions.

After reading the following topic:

https://github.com/firebase/firebase-tools/issues/33

The @TheRoccoB user explains how to host the static Web application in Firebase Hosting and redirect traffic from a URL to Cloud Functions.

What I did was map the routes that I have to index as:

{         "source": "/ shop / *",         "function": "ssr"       },       {         "source": "/ / promotions / **",         "function": "ssr"       }

Since "ssr" is the name of my function in Cloud Functions. So I used the library https://github.com/prerender/prerender-node to check if the request is from a google crowler, in case I redirect the request to a https://github.com/prerender/prerender server.

const prerender = express (); prerender.use (cors); prerender.use (     require ('prerender-node')     // .set ('prerenderServiceUrl', 'http: // localhost: 3000')     .set ('prerenderToken', ' TOKEN ') ); prerender.use (require ('prerender-node'). set ('beforeRender', function (req, done) {     // do you need to do?     console.log ('Rendering URL:', req.path); done (); })); prerender.use (require ('prerender-node') set ('afterRender', function (err, req, prerender_res) {     // do you need to do?     console.log (req.path + 'rendering completed!');     console.log ('Errors:', err); })); prerender.get ('*', (req, res) => {     console.log ('Calling function for URL:', req.path);     res.set ('Cache-Control', 'public, max-age = 300, s-maxage = 600');     res.status (200) .send (fs.readFileSync ('./ www / index.html'). toString ()); }); exports.ssr = functions.https.onRequest (prerender);

thoop commented 6 years ago

Interesting! To answer those questions, you do not need to override beforeRender or afterRender.

So does this pull in express for cors? You probably don't need express if you can set up cors and just use prerender-node directly to clean things up. But if it's working with express, then that's great.

fs.readFileSync is going to pause the node execution thread and wait for the file so you should probably change that to fs.readFile to send the response only once the file has been loaded without tying up the execution thread. Is there a reason you used the synchronous version of that function?