FetchError - 使用Rendertron进行服务器端渲染 - Firebase& Angular 5

时间:2018-03-01 14:37:22

标签: angular firebase fetch google-cloud-functions angular5

对于我的生活,我找不到适用于我的 Angular 5 站点的服务器端渲染解决方案。在我最近的尝试中,我一直在关注 AngularFirebase.com提供的解决方案https://angularfirebase.com/lessons/seo-angular-part-1-rendertron-meta-tags/

我的应用的所有内容都是硬编码的,所以我跳过了本教程的第一部分。我确实使用 Firestore 2 ,但仅用于捕获联系表单上的字段。我的路由非常简单,都包含在 module.ts 文件中。我所做的事情的内容包含在我的 index.js 文件中:

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

我已经使用这些重写设置了 firebase.json

"rewrites": [
      {
        "source": "**",
        "function": "app"
      }
    ]

所有内容都成功部署,但是当我访问我的网站时,我的Firebase功能日志会吐出:

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

根据我的阅读here,似乎可能是我格式化网址的方式,但我尝试过以不同方式对其进行格式化。在第二个提取语句fetch( https:// $ {appUrl} / )我删除了&#34; https://&#34;,但提取需要一个绝对网址。

如何解决此冲突?任何建议表示赞赏!

1 个答案:

答案 0 :(得分:0)

您好像是免费的Firebase游戏吗?如果是这样,您无法访问任何网络,只能使用Google API。需要启用结算功能。

您是否考虑过在FB云功能中运行Angular Universal? Angularfire Lite支持这一点,我相信Angularfire2如果不是已经太早了。也可以在没有它们的情况下完成,但可能存在一些障碍,例如在服务器上手动关闭套接字连接,在zone.runOutsideAngular等中包装东西。