reactjs - 从域调用时,Firebase 函数不执行
问题描述
我有一个使用 NodeJS 创建的带有 Firebase 后端的 React Web 应用程序。我使用 Firebase 函数。当我从 localhost 或 Postman 调用它们时,我的 Firebase 函数就会执行。但是当我从我的域 (moonio.io) 调用函数时,它们没有被执行,唯一发生的事情是我取回了我的 index.js 文件。因此,我怀疑我的问题是由 firebase.json 文件的托管部分的重写引起的(api 地址“https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api”被重写到“/index.html”)?
firebase.json
{
"hosting": [
{
"target": "app",
"public": "app/build",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
"functions": {
"source": "functions"
}
}
用于 Firebase 函数的 package.json
{
"name": "functions",
"description": "Cloud Functions for Firebase",
"scripts": {
"lint": "eslint .",
"serve": "firebase emulators:start --only functions",
"shell": "firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "12"
},
"main": "index.js",
"dependencies": {
"axios": "^0.21.1",
"express": "^4.17.1",
"firebase": "^8.1.1",
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.13.1",
"google-auth-library": "^6.1.3",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"eslint": "^5.12.0",
"eslint-plugin-promise": "^4.0.1",
"firebase-functions-test": "^0.2.0"
},
"private": true
}
我的 React 应用程序的 package.json
{
"name": "cryptotracker",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
"@fortawesome/free-solid-svg-icons": "^5.15.1",
"@fortawesome/react-fontawesome": "^0.1.13",
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.57",
"axios": "^0.20.0",
"chart.js": "^2.9.4",
"chartjs": "^0.3.24",
"colorthief": "^2.3.2",
"cra-template": "1.0.3",
"firebase": "^8.2.3",
"history": "^5.0.0",
"install": "^0.13.0",
"jwt-decode": "^3.1.2",
"lodash": "^4.17.20",
"npm": "^6.14.10",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-chartjs-2": "^2.11.1",
"react-dom": "^16.13.1",
"react-google-login": "^5.2.2",
"react-hook-form": "^6.9.1",
"react-loading-skeleton": "^2.1.1",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"react-virtualized-select": "^3.1.3",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"retry-axios": "^2.3.0",
"styled-components": "^5.2.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"proxy": "https://europe-west3-cryptocurrency-tracker-moonio.cloudfunctions.net/api"
}
解决方案
几个小时后,我终于发现了问题。
- 需要向 firebase.json 文件添加另一个重写以处理 api。所有对 api 的请求都必须到 Firebase 函数中对应的 api 函数,其他所有请求都到 index.html,根据单页应用的要求。因此,firebase.json 的重写部分需要如下所示:
"rewrites": [
{
"source": "/api/**",
"function": "api"
},
{
"source": "!/api/**",
"destination": "/index.html"
}
]
- package.json 文件中的代理仅用于开发目的。它在生产中不起作用。只要您设置了自定义域,Firebase 就会自动将此域链接到您的函数。因此,由于我的自定义域是 moonio.io,因此可以通过向 moonio.io/api/<FUNCTION_NAME> 发送请求来执行 Firebase 功能。为了使对这些端点的请求正常工作,您还必须在 node.js 中的函数设置中的请求 url 中包含“/api”。我正在使用 express,所以我的 index.js 文件的示例函数如下所示(注意“/api”是 url 的一部分):
const app = require("express")();
const functions = require("firebase-functions");
app.post("/api/signin", signIn);
exports.api = functions.region("us-central1").https.onRequest(app);
- 此外,在从前端向 Firebase 函数发出请求时,必须在 url 的开头包含“/api”,正如我在以下示例函数中所做的那样:
axios.post("/api/signin", userData)
- Firebase 函数仅适用于 us-central1 中的 Firebase 托管。如果您使用的是其他位置,请根据我在第 2 部分中的代码示例进行更改。
推荐阅读
- generics - 如何拥有具有关联类型的动态泛型类型或动态特征?
- c# - 仅接受类似 excel 的行或列单元格范围的正则表达式
- sql-server - 是否有用于删除包含文本和整数的字符串的 SQL 函数,以及如何使用它?
- php - 在 Array PHP 中下载图像的脚本
- swift - 更新代码以避免在 swift 5 中使用 UnsafeMutableBytes 出现弃用警告时出错
- python - 如何解析无法识别的参数?
- c++ - 如何将 strlen() 与二维数组一起使用?
- javascript - 如何使用 mocha/jest 模拟/测试事件监听器?
- reactjs - 如何使用 ReactJs 格式化嵌入的推文?
- html - AEM - CRXDE:cq:对话框未显示组件