看来有人也有同样的问题:https://github.com/firebase/firebase-functions/issues/1050
问题
我已经将我的项目结构移动到具有以下结构的monorepo:
/
|
| - node_modules/
|
| - packages/
| - - app/
| - - - - index.js
| - - - - package.json
| - - functions/
| - - - - src/
| - - - - - - helloWorld.function.js
| - - - - - - index.js
| - - - - package.json
|
| - .firebaserc
| - firebase.json
| - firestore.indexes.json
| - firestore.rules
| - package.json
| - yarn.lock
| - LICENSE.md
据我所知,我们的函数所依赖的所有代码都必须在functions
目录中。但是...当我运行yarn install
时,我的functions
的node_modules
保存在root node_modules folder
中。
然后,如果我从项目的根目录运行firebase deploy
,我会得到错误:
错误:解析函数触发器时出错。
默认Firebase应用程序不存在。请确保在使用任何Firebase服务之前调用initializeApp()。
- 注意:我没有做任何代码更改...在将项目配置为monorepo结构之前,一切都运行良好。*
我解决这个问题的尝试
我尝试在根包.json中定义工作空间时使用nohoist:
{
"private": true,
"name": "@company/project",
"version": "1.0.0",
"description": "Project monorepo",
"repository": "...",
"license": "MIT",
"author": {
"name": "Raul",
"email": "...
},
"scripts": {
"app": "yarn workspace @company/app start",
"documentation": "yarn workspace @company/documentation start",
"server": "yarn workspace @company/server start"
},
"workspaces": {
"packages": ["packages/*"],
"nohoist": ["**/@company/server"] <---- HERE
}
}
-* 注意:当我运行yarn server
时,函数shell正确启动。*
但是...出于某种原因,在重新安装所有东西之后:
rm -rf node_modules (everywhere)
yarn cache clean
yarn install
函数包的依赖安装在根目录node_modules
!
有什么想法吗
这是我的函数node_modules在安装了dep之后的样子:
node_modules/
.bin/
eslint
eslint-config-prettier
firebase-functions
functions-framework
functions-framework-nodejs
image_size
uuid
qs/
uuid/
这些是所需的依赖项(安装在根package.json中,这不是我期望的行为):
"name": "@company/server",
...
"dependencies": {
"@google-cloud/functions-framework": "^3.1.1",
"@google-cloud/translate": "^6.3.1",
"@google-cloud/vision": "^2.4.2",
"@googlemaps/google-maps-services-js": "^3.3.3",
"axios": "^0.27.2",
"camelcase": "^6.3.0",
"dotenv": "^16.0.1",
"expo-server-sdk": "^3.6.0",
"firebase-admin": "^10.3.0",
"firebase-functions": "^3.21.2",
"glob": "^7.2.0",
"image-size": "^1.0.1",
"lodash": "^4.17.21",
"moment": "^2.29.3",
"qs": "^6.10.3",
"sharp": "^0.30.6",
"uuid": "^8.3.2"
},
"devDependencies": {
"eslint": "^8.3.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^4.3.1",
"firebase-functions-test": "^0.2.0"
}
更新
我没有在根目录中使用nohizing,而是将此段放在packages/functions/package.json
中:
workspaces: { nohoist: ["**"] }
而且所有的deps都是本地安装的!
但是...当我做firebase deploy
时,同样的错误。如果不是从根文件夹运行命令,而是从packages/functions/package.json
运行,则部署成功。
为什么?发生什么事了?
这是我的firebase.json
文件:
{
"functions": {
"predeploy": ["yarn --cwd \"$RESOURCE_DIR\" lint"],
"source": "packages/functions"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
}
}
2条答案
按热度按时间ddrv8njm1#
我已经开发了一个解决方案,并就此写了一篇文章。下面是摘录,但这里是full article
Firebase的问题
当部署到Firebase时,它希望上传一个文件夹,就像传统的单个包存储库一样,包含源文件以及声明其外部依赖关系的清单文件。在其云部署管道中接收到文件后,它会检测包管理器并运行安装和构建。
在一个monorepo中,尤其是一个私有的,你的Firebase代码通常依赖于同一个仓库中的一个或多个共享包,你不想在任何地方发布它们。
一旦Firebase尝试在云中查找这些依赖项,就无法找到它们,部署就会失败。
杀出一条血路
使用bundler
为了解决这个问题,你可以尝试使用Webpack这样的打包器将Firebase代码与共享包代码结合起来,然后从发送到Firebase的package.json清单中删除这些包,这样它就不知道这些包的存在。
不幸的是,这种策略很快就成了问题。。
如果共享包本身没有在其输出中捆绑所有依赖项,Firebase将不知道共享代码依赖于什么,因为您没有包含或安装这些清单。
您可以尝试捆绑所有内容,但是如果您的共享包依赖于您的Firebase包也依赖的东西,那么您现在有一部分代码运行依赖项的内部捆绑副本,而另一部分则使用来自包管理器安装的不同位置的相同依赖项。
此外,有些库确实不喜欢捆绑,根据我的经验,包括Firebase和Google客户端库。你会很快发现自己试图通过bundler设置将事情外部化,以便让事情工作。
即使您设法完成了所有这些工作,您可能正在创建大型捆绑包,这可能会导致云功能的冷启动时间出现问题。
不完全是可靠或可扩展的解决方案。
打包和链接本地依赖
一种可以说是更优雅的方法涉及将本地依赖项打包到tarball中(类似于将包发布到NPM的方式),并将结果复制到构建输出,然后将其链接到更改的清单文件中。
这可以很好地工作,因为它基本上类似于如果从外部域安装这些包,Firebase代码将如何工作。
无论您是手动执行此操作,还是编写shell脚本来处理这些事情,对我来说仍然感觉非常繁琐和脆弱,但我认为如果您的本地依赖关系很简单,这是一个可行的解决方案。
然而,一旦您的共享包依赖于其他共享包,这种方法很快就会变得棘手,因为这样您就需要打包和调整多个级别的东西。
我的解决方案
我创建了isolate-package。这个名字是通用的,因为它不包含任何特定于Firebase的东西,尽管我目前不知道任何其他隔离输出的用例。
它采用了与前面在打包和链接依赖项中描述的方法类似的方法,但是采用了更复杂的方法。它被设计为处理不同的设置和包管理器,它完全隐藏了用户的复杂性。
它公开的隔离二进制文件可以简单地添加到Firebase predeploy钩子中,就是这样!
这还允许您从多个不同的包部署到Firebase,并保持配置位于同一位置,而不是分散在monorepo根目录中。
对于绝大多数用例来说,它应该是零配置的,并且被设计为与所有包管理器兼容。
fgw7neuy2#
解决方法(不是正确的解决方案,只是一个技巧):
与其使用
nohoist
在packages/functions
目录中本地安装所有dep,不如将其从yarn workspaces
中排除?为此,请将root的
package.json
更新为:(
packages/functions
未作为工作区包含在内。)测试:
现在,如果您运行(在项目中的任何位置)
firebase deploy
,一切都很好...部署成功,我们所有的后端DEP都安装在本地(这是必需的,因为所有的云函数代码都必须在函数文件夹中)。这个error也解决了!
优点:
您可以维护单一存储库结构并毫无问题地部署云功能。
缺点:
这是一个棘手的解决方案。。当你从项目的根目录运行
yarn install
时,packages/functions/package.json
依赖项不会被安装(因为我们已经从工作区中删除了它,以便在本地安装它们)。为了解决这个小问题,在根目录
package.json
中,编写以下代码:在我的例子中: