【发布时间】:2020-04-19 22:19:29
【问题描述】:
我有一个托管在 Firebase 中的 SPA,我一直在使用 Firestore 来存储数据。我还利用云功能进行一些 https 操作和某些其他数据库读写。
最近我使用 Angular Universal 更新了从客户端到服务器端的渲染逻辑,这非常成功。这是我关注的链接:https://fireship.io/lessons/angular-universal-firebase/
基本上,我已经创建了一个 https 函数来在云函数中呈现 ssr。
const universal = require(`${process.cwd()}/dist/server`).app;
exports.api = functions.https.onRequest(app); //Application related endpoint line makepayment, createorder etc.,
exports.ssr = functions.https.onRequest(universal);
现在,一旦我部署了这个功能,所有的api https 功能,我曾经访问过db.collection
或db.doc 开始抛出错误。以下是对db.doc 的相同调用。
db.doc("samplecollection/docid")
.get()
.then(function (doc) {
console.log('doc.data', doc.data());
})
.catch(function (error) {
console.log('Error in fetching samplecollection doc', error);
});
现在,当我尝试执行上述操作时,出现以下错误。
Error in autogenerated TypeError [ERR_INVALID_ARG_TYPE]: The "path"
argument must be of type string. Received type object
at validateString (internal/validators.js:125:11)
at Object.basename (path.js:744:5)
at GrpcClient.loadProto (sampleproject\functions\node_modules\google-gax\build\src\grpc.js:133:29)
at new FirestoreClient (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\v1\firestore_client.js:121:32)
at ClientPool.Firestore._clientPool.pool_1.ClientPool [as clientFactory]
(sampleproject\functions\node_modules\@google-cloud\firestore\build\src\index.js:302:26)
at ClientPool.acquire (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\pool.js:67:35)
at ClientPool.run (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\pool.js:124:29)
at Firestore.readStream (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\index.js:947:26)
at Firestore.getAll_ (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\index.js:680:14)
at initializeIfNeeded.then (sampleproject\functions\node_modules\@google-cloud\firestore\build\src\index.js:650:61)
at ZoneDelegate.invoke (sampleproject\functions\dist\server.js:5715:30)
at Zone.run (sampleproject\functions\dist\server.js:5472:47)
at sampleproject\functions\dist\server.js:6213:38
at ZoneDelegate.invokeTask (sampleproject\functions\dist\server.js:5750:35)
at Zone.runTask (sampleproject\functions\dist\server.js:5517:51)
at drainMicroTaskQueue (sampleproject\functions\dist\server.js:5930:39)
at process._tickCallback (internal/process/next_tick.js:68:7)
我不太确定为什么错误说 “路径”参数必须是字符串类型。收到类型对象。我尝试将文档路径分配给变量并使用typeof 检查其类型,它仍然显示为string。
要注意的关键点是 - 如果我删除复制到 functions 目录中的 ssr、函数和 dist 文件夹,则具有相同代码行的所有内容都可以正常工作。所以,我强烈怀疑,这与 SSR 有关。
我为此做了很多谷歌搜索,但没有一个人有这个 SSR 设置。 有人可以为我指出正确的方向,或者让我知道是否有人遇到过 Angular Universal SSR 的这个问题并找到了解决方案?
更新 - 1
我在webpack.server.config.js 文件中设置了以下选项。这会是个问题吗?
node: {
__dirname: false
},
更新 - 2
这是为开发和生产环境配置的 firebase.json。
{
"hosting": [
{
"public": "dist/browser",
"target": "staging",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"function": "ssr"
}
],
"headers": [
{
"source": "**/*.@(jpg|jpeg|gif|png|svg|js|css|css?*|eot|otf|ttf|ttc|woff|woff2)",
"headers": [
{
"key": "Access-Control-Allow-Origin",
"value": "*"
},
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
},
{
"source": "404",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=7200"
}
]
}
]
},
{
"public": "dist",
"target": "production",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
],
"functions": {
"include": ["**/views/**"]
}
}
现在,我刚刚在staging 中配置了这个,即[开发环境] 进行测试,但是这个问题甚至会影响到生产环境,因为两者的云功能将保持不变。
更新 - 3
经过进一步调查,我注意到 firestore_client.js 存在于 functions 依赖项的 node_modules 中,在路径 node_modules/@google-cloud/firestore/build/src/v1 下有以下代码来识别它是浏览器还是不是。
const isBrowser = typeof window !== 'undefined';
if (isBrowser) {
opts.fallback = true;
}
.....
.....
.....
// Load the applicable protos.
// For Node.js, pass the path to JSON proto file.
// For browsers, pass the JSON content.
const nodejsProtoPath = path.join(__dirname, '..', '..', 'protos', 'protos.json');
const protos = gaxGrpc.loadProto(opts.fallback ? require('../../protos/protos.json') : nodejsProtoPath);
所以firestore_client.js 通过检查typeof window !== undefined 是否可以识别这是否是浏览器。但是,在我的 SPA 的 server.ts 中,我从 domino 库中定义了 global['window'] = win。添加它是因为它会抛出 window is not defined ReferenceError.
基本上,这意味着firestore_client.js 能够通过server.js 确定window 对象,生成并保存在functions 文件夹中,因此它传递作为对象的protos.json 文件内容,而不是路径。看了上面写在上述文件中的cmets,感觉这里应该传递一个文件的路径,而不是nodejs环境的对象。
任何想法,我现在如何克服这个问题?
【问题讨论】:
-
我不知道如何解决这个特定的错误,但我尝试了使用 Firebase 云功能的 SSR 并得到了一些我无法解决的其他错误。如果您可以选择使用 appengine,那么我会选择它 (fireship.io/lessons/angular-universal-firebase)
-
@michelepatrassi .. 不太确定,如果这是一个不错的选择。从来没有继续尝试过,也担心定价,因为我们的项目目前处于火焰计划中。这可能证明我们代价高昂。
-
您的
firebase.json看起来如何?您是否指定了"source"作为项目根目录? -
@Vojtech.. 更新了我的问题。如果有帮助,请告诉我。
-
我检查了我的配置,您似乎在
functions配置中没有source,请尝试添加"source": "folderName",其中文件夹名称将是您的云功能所在文件夹的名称相对于firebase.json
标签: node.js angular firebase google-cloud-firestore angular-universal