如何将所有服务器请求重定向到 Firebase 托管中的一个函数
how to redirect all server requests to a function in Firebase Hosting
尝试使用 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.
如果您希望将每一个 URL 重定向到您的主机到 Cloud Functions 中的快速应用程序,您将需要执行以下操作:
确保您的 public 托管文件夹中没有 index.html(否则它将始终使用路径 /
)。
在 firebase.json 中配置 Firebase 托管以将所有 url 重写为一个函数(您目前正在 "hosting" 块中执行此操作,这很好):
"rewrites": [
{
"source": "**",
"function": "contentServer"
}
]
编写一个导出的 Cloud Function 与重写中的函数同名,并附加一个处理通配符 *
的路由的快速应用程序。在您的函数文件夹中的 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"。
尝试使用 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.
如果您希望将每一个 URL 重定向到您的主机到 Cloud Functions 中的快速应用程序,您将需要执行以下操作:
确保您的 public 托管文件夹中没有 index.html(否则它将始终使用路径 /
)。
在 firebase.json 中配置 Firebase 托管以将所有 url 重写为一个函数(您目前正在 "hosting" 块中执行此操作,这很好):
"rewrites": [
{
"source": "**",
"function": "contentServer"
}
]
编写一个导出的 Cloud Function 与重写中的函数同名,并附加一个处理通配符 *
的路由的快速应用程序。在您的函数文件夹中的 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"。