node.js - 迁移 Angular Universal firebase 后云函数抛出错误

标签 node.js angular firebase google-cloud-firestore angular-universal

我有一个托管在 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);

现在,一旦我部署了这个函数,我用来访问db.collection的所有api https函数 或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、function 和 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。添加此内容是因为它会抛出窗口未定义引用错误。

基本上,这意味着 firestore_client.js 能够通过 server.js 确定 window 对象,生成并保存在 functions 文件夹,因此它传递的是 protos.json 文件内容,它是一个对象,而不是路径。读了上述文件中的注释,我觉得这里应该传递文件的路径,而不是nodejs环境的对象。

知道我现在如何克服这个问题吗?

最佳答案

这不是您希望得到的答案,但无论如何还是发布它。

不久前我尝试过基本相同。我使用 Firebase 身份验证和实时数据库而不是 Firestore。另外,我使用了 AngularFire2。我不确定你是否也在使用这个。构建很好,但是我总是会遇到运行时异常。

我发现多个声明声称 Firebase 身份验证和实时数据库无法与 ssr 一起使用,因为它依赖于某些浏览器功能。不幸的是我现在找不到他们了。不确定这是否与 firebase 相关或 AngularFire 相关。

我搜索了多个关于 ssr 与实时数据库相结合的教程/帖子。除了一个我找不到任何一个。 This指南解释了如何将 Firestore 与 SSR 结合使用。不同之处在于他们使用 AngularFireLite而不是 AngularFire。

关于node.js - 迁移 Angular Universal firebase 后云函数抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59543208/

相关文章:

json - Angular environment.ts 问题 JSON。然而 environment.prod.ts

ios - 获取随机 Firebase 数据库条目

node.js - 如何在 nodejs 中编写 KSQL 查询?

python - Node api、Reactjs、Python fast api 和 React Native 的 Azure 托管设置

javascript - 为基于 Electron-vue 的应用程序设置 key 过期

javascript - 我不知道如何在 angular2 中包含 js 文件和使用 jquery

angular - chartjs 高度不跟随父容器

javascript - AngularFire:恢复匿名 session

android - 最新版本如何使用getdownloadurl?

javascript - Shelljs:如何取消异步进程?