For the life of me, I cannot find a server-side rendering solution that works for my Angular 5 site. In my most recent attempt, I've been following a solution provided by AngularFirebase.com: https://angularfirebase.com/lessons/seo-angular-part-1-rendertron-meta-tags/
All of the content of my app is hardcoded, so I skipped the first part of the tutorial. I do use Firestore 2, but only to capture the fields on my contact form. My routing is very simple, all contained within the module.ts file. The meat of what I've done is contained within my index.js file:
const functions = require('firebase-functions');
const express = require('express');
const fetch = require('node-fetch');
const url = require('url');
const app = express('');
const appUrl = 'customapp.firebaseapp.com';
const renderUrl = 'https://render-tron.appspot.com/render';
function generateUrl(request) {
return url.format({
protocol: request.protocol,
host: appUrl,
pathname: request.originalUrl
});
}
function detectBot(userAgent){
const bots = [
'bingbot',
'yandexbot',
'duckduckbot',
'slurp',
//Social
'twitterbot',
'facebookexternalhit',
'linkedinbot',
'embedly',
'pinterest',
'W3C_Validator'
]
const agent = userAgent.toLowerCase();
for (const bot of bots) {
if (agent.indexOf(bot) > -1) {
console.log('bot detected', bot, agent);
return true;
}
}
console.log('no bots found');
return false;
}
app.get('*', (req, res) =>{
const isBot = detectBot(req.headers['user-agent']);
if (isBot) {
const botUrl = generateUrl(req);
fetch(`${renderUrl}/${botUrl}`)
.then(res => res.text())
.then(body => {
res.set('Cache-Control', 'public, max-age=300, s-maxage=600');
res.set('Vary', 'User-Agent');
res.send(body.toString())
});
} else {
fetch(`https://${appUrl}/`)
.then(res => res.text())
.then(body => {
res.send(body.toString());
});
}
});
exports.app = functions.https.onRequest(app);
I've set up my firebase.json with these rewrites:
"rewrites": [
{
"source": "**",
"function": "app"
}
]
Everything deploys successfully, but when I hit my site, my Firebase functions logs spit out:
Function execution took 677 ms, finished with status: 'crash'
warning FetchError: request to https://test-297a3.firebaseapp.com/ failed, reason: getaddrinfo ENOTFOUND test-297a3.firebaseapp.com test-297a3.firebaseapp.com:443
at ClientRequest.<anonymous> (/user_code/node_modules/node-fetch/lib/index.js:1376:11)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at TLSSocket.socketErrorListener (_http_client.js:310:9)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)
at connectErrorNT (net.js:1025:8)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickDomainCallback (internal/process/next_tick.js:128:9)
warning . Unhandled rejection
From what I read here, it seemed like it could be how I'm formatting the URL, but I've tried formatting it differently. In the second fetch statement fetch(
https://${appUrl}/)
I removed "https://", but fetch requires an absolute URL.
How can I resolve this conflict? Any advice is appreciated!