【问题标题】:FetchError - Server-side rendering with Rendertron - Firebase & Angular 5FetchError - 使用 Rendertron 进行服务器端渲染 - Firebase 和 Angular 5
【发布时间】:2018-08-09 15:48:30
【问题描述】:

在我的一生中,我找不到适用于我的 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 看来,这似乎是我格式化 URL 的方式,但我尝试了不同的格式化方式。在第二个 fetch 语句 fetch(https://${appUrl}/) 我删除了“https://”,但 fetch 需要一个绝对 URL。

我该如何解决这个冲突?任何建议表示赞赏!

【问题讨论】:

  • 使用 NGINX 和 Rendertron 的不同方法here

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


【解决方案1】:

您似乎在使用免费层级 Firebase?如果是这样,则您无权访问任何网络,只能使用 Google API。需要启用结算功能。

您是否考虑过在 FB 云函数中运行 Angular Universal? Angularfire Lite 支持这一点,我相信 Angularfire2 会为时过早,如果还没有的话。没有它们也可以完成,但可能会遇到一些障碍,比如在服务器上手动关闭套接字连接,在 zone.runOutsideAngular 中包装东西等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 2017-04-04
    • 2018-03-06
    • 2019-02-12
    • 1970-01-01
    相关资源
    最近更新 更多