【问题标题】:how to redirect all server requests to a function in Firebase Hosting如何将所有服务器请求重定向到 Firebase 托管中的函数
【发布时间】:2018-10-08 19:50:32
【问题描述】:

尝试使用 Firebase 实现 SSR,因此我使用了一个函数来预渲染 React 应用程序的每个页面。除了主页之外它运行良好,所以它必须是firebase重定向上的匹配错误,或者可能是快速路由本身。

firebase.json

{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint"
    ]
  },
  "hosting": {
    "public": "build",
    "rewrites": [
      {
        "source": "**",
        "function": "contentServer"
      }
    ],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

contentServer.js

import * as functions from 'firebase-functions';
import * as fs from 'fs';
import * as path from 'path';

import React from 'react';
import Helmet from 'react-helmet';
import { renderToString } from 'react-dom/server';
import Server from '../browser/Server.js';

const express = require('express');

const app = express();

// might be this? Also tried /**

app.get(['**'], (request, response) => {
  const context = {};
  const location = request.url;
  console.log('Processing request for ', location);

  let appCode;
  try {
    appCode = renderToString(<Server context={context} location={location} />);
  } catch (err) {
    appCode = 'with error';
  }

  // const appState = {
  //   pageTitle: 'Hello World',
  // };

  // const preloadedState = JSON.stringify(appState).replace(/</g, '\\u003c');
  const fileName = path.join(__dirname, '../index.html');
  const htmlTemplate = fs.readFileSync(fileName, 'utf8');
  const head = Helmet.renderStatic();

  const responseString = htmlTemplate
    .replace('<div id="root"></div>', `<div id="root">${appCode}</div>`)
    .replace('<title>React App</title>', `${head.title}\n${head.link}`);
  return response.send(responseString);
});

export default functions.https.onRequest(app);

卷曲

我跑firebase serve --only functions,hosting

然后使用curl查看响应:

curl http://localhost:5000 - does not render the home page - just the standard react page
curl http://localhost:5000/ - also does not work - just the standard react page.
curl http://localhost:5000/contact-us - works well and returns the contact us page, all other pages on the site work and trigger the function.

【问题讨论】:

    标签: javascript firebase google-cloud-functions firebase-hosting


    【解决方案1】:

    如果您希望将每个 URL 重定向到您的主机到 Cloud Functions 中的快速应用程序,您需要执行以下操作:

    确保您的公共托管文件夹中没有 index.html(否则它将始终使用路径 /)。

    在 firebase.json 中配置 Firebase 托管以将所有 url 重写为一个函数(您目前正在“托管”块中执行此操作,这很好):

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

    编写一个导出的云函数与重写中的函数同名,并附加一个处理带有* 通配符的路由的快速应用程序。在您的函数文件夹中的 index.js 中,至少:

    const functions = require('firebase-functions')
    const express = require('express')
    
    const app = express()
    
    app.get("*", (request, response) => {
        response.send("OK")
    })
    
    exports.contentServer = functions.https.onRequest(app)
    

    如果您使用firebase serve --only hosting,functions 在本地运行此程序,您发送到 localhost:5000 的每个路径都会显示“OK”。

    【讨论】:

    • 谢谢道格。删除 index.html 是可行的,但这很痛苦,因为很难用非弹出的 create-react-app 重命名该文件(从我读到的关于此事的内容)。如果可以改变托管行为,SSR 会运行良好而无需弹出 webpack 配置?我可以以某种方式将此作为功能请求添加到 Firebase 托管吗?
    • 为了记录,我将 index.html 添加到忽略列表中。因此它适用于已部署的环境,但不适用于本地“firebase 服务”。没什么大不了的。
    • 您可以随时在此处提交功能请求:firebase.google.com/support/contact/bugs-features
    • @RichardG 我发现如果你像这样使用 express Router 中间件,你不必删除 index.html 文件。 router.use("^/$", serverRenderer); app.use(router);
    猜你喜欢
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    • 2016-12-16
    • 2012-11-22
    相关资源
    最近更新 更多