Firebase功能+ monorepo-部署不工作+ DEPS未在本地安装

发布于 2025-02-10 06:59:29 字数 3945 浏览 3 评论 0原文

看起来某人在这里有同样的问题: https://github.com/firebase/firebase/firebase/firebase - 函数/问题/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

据我所知,我们的所有函数所依赖的所有代码都必须在函数目录中。但是...当我运行纱线安装时,我function> functionnode_modules保存在root node_modules文件夹

然后,如果我从项目的根部运行firebase部署,我会得到错误:

错误:解析函数触发器时发生错误。

不存在默认的firebase应用程序。在使用任何firebase服务之前,请确保您致电ditiarizeapp()。

注意:我还没有做任何代码更改...在将项目配置为MonorePo结构之前,一切都很好。

我试图解决此问题的尝试

,我试图尝试使用 nohoist> nohoist 在定义我的工作区时,我的root pockage.json:json:json:json:json:json:json:json:json:json:

{
  "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
  }
}

- 注意:当我运行纱线服务器 函数shell的启动正确。

,但由于某种原因,在重新安装所有内容之后:

rm -rf node_modules (everywhere)
yarn cache clean
yarn install

函数软件包的依赖项安装在root node_modules

中吗?


这就是我的函数node_modules安装deps之后的样子:

node_modules/ 
  .bin/ 
     eslint
     eslint-config-prettier
     firebase-functions
     functions-framework
     functions-framework-nodejs
     image_size
     uuid
  qs/
  uuid/

这些是所需的依赖项(已安装在root 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"
  }


更新,

而不是在root中放置,我已放置packages/functions/package.json中的该细分市场

workspaces: { nohoist: ["**"] }

都在本地安装!

但是...当我做firebase部署时,相同的错误。如果不是从根文件夹中运行命令,我会从wake> packages/functions/package.json进行部署成功。

为什么?怎么了?

这是我的firebase.json文件:

{
  "functions": {
    "predeploy": ["yarn --cwd \"$RESOURCE_DIR\" lint"],
    "source": "packages/functions"
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  }
}

Looks like someone has the same problem here: https://github.com/firebase/firebase-functions/issues/1050

Problem

I have moved my project structure to a monorepo with the following structure:

/
|
| - 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

As far as I know, all code our functions depends on must be inside the functions directory. But... when I run yarn install, the node_modules of my functions are saved in the root node_modules folder.

Then, if I run firebase deploy from the root of my project, I get the error:

Error: Error occurred while parsing your function triggers.

The default Firebase app does not exist. Make sure you call initializeApp() before using any of the Firebase services.

Note: I haven't made any code change... before configuring the project to the monorepo structure, everything worked fine.

My attempt to solve this problem

I have tried to use nohoist when defining my workspaces inside my root package.json:

{
  "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
  }
}

-Note: when I run yarn server the functions shell is started correctly.

But... for some reason, after reinstalling everything:

rm -rf node_modules (everywhere)
yarn cache clean
yarn install

The dependencies of the functions packages are installed in the root node_modules!

Any ideas?


This is how my functions node_modules looks like after installing the deps:

node_modules/ 
  .bin/ 
     eslint
     eslint-config-prettier
     firebase-functions
     functions-framework
     functions-framework-nodejs
     image_size
     uuid
  qs/
  uuid/

And these are the dependencies required (which are installed in the root package.json, which is not the behavior I expect):

 "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"
  }


UPDATE

Instead of nohoisting in the root, I have placed this segment in the packages/functions/package.json:

workspaces: { nohoist: ["**"] }

and all the deps are installed locally!

But... when I do firebase deploy, same error. If instead of running the command from the root folder I do it from packages/functions/package.json the deployment is successful.

Why? What is happening?

This is my firebase.json file:

{
  "functions": {
    "predeploy": ["yarn --cwd \"$RESOURCE_DIR\" lint"],
    "source": "packages/functions"
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一向肩并 2025-02-17 06:59:30

解决方法(不是正确的解决方案,只是一个技巧):

而不是使用nohoistpackages/functions/functions目录中在本地安装所有dep 目录,而如何将其排除在<<<代码>纱线工作区?

为此,将您的root的package.json更新为:(

  "workspaces": [
    "packages/app",
    "packages/documentation"
  ]

packages/functions不包括作为工作区。)

测试:

现在,如果您运行您的项目)firebase部署,一切正常...部署成功,我们所有的后端dep均已在本地安装(这是必需的,因为所有云功能代码必须在功能文件夹中)。

另外,此 error 也已解决!

优点:

您可以维护单座结构并没有问题部署云功能。

缺点:

这是一个棘手的解决方案...当您从项目的根部运行YARN install时,packages/functions/package.json依赖项未安装(因为我们 工作区中删除它以便在本地安装它们

{
  "scripts": {
    ...,
    "postinstall": "cd path/to/your/functions && yarn install", // automatically executed after running `yarn install`
  }
}

{
  "scripts": {
    ...,
    "postinstall": "cd packages/functions && yarn install", // automatically executed after running `yarn install`
  }
}

Workaround (Not the correct solution, just a trick):

Instead of using nohoist to installing all the deps locally inside the packages/functions directory, what about excluding it from the yarn workspaces?

For this, update your root's package.json to:

  "workspaces": [
    "packages/app",
    "packages/documentation"
  ]

(packages/functions is not included as a workspace.)

Test it:

Now, if you run (wherever you want in your project) firebase deploy, everything works fine... the deployment is successful and all our backend deps are installed locally (it is required, since all the cloud functions code must be inside the functions folder).

Also, this error is solved too!

Pros:

You can maintain the monorepository structure and deploy your cloud functions without problems.

Cons:

This is a tricky solution... when you run yarn install from the root of your project, packages/functions/package.json dependencies are not installed (as we have remove it from the workspace in order to install them locally.)

In order to solve this little issue, in your root package.json, write the following:

{
  "scripts": {
    ...,
    "postinstall": "cd path/to/your/functions && yarn install", // automatically executed after running `yarn install`
  }
}

in my case:

{
  "scripts": {
    ...,
    "postinstall": "cd packages/functions && yarn install", // automatically executed after running `yarn install`
  }
}
提笔落墨 2025-02-17 06:59:29

我已经开发了一个解决方案,并写了一篇文章。以下是一个
摘录,但这是 full
文章

firebase的问题

部署到firebase时,它想要上传一个文件夹
传统的单个软件包存储库,包含源文件
以及一个宣布其外部依赖性的清单文件。
在其云部署管道中收到文件后,然后
检测软件包管理器并运行安装和构建。

在monorepo中,尤其是私人的壁炉代码
通常取决于一个或多个共享软件包
存储库,您不想在任何地方发布它们。

一旦Firebase试图在云中查找这些依赖性
找不到并且部署失败。

黑客出路

使用捆绑器

为了解决这个问题,您可以尝试使用像WebPack这样的捆绑者
将您的firebase代码与共享软件包代码相结合,然后
从软件包中删除这些包装。
发送到firebase,所以它甚至不知道这些包都存在。

不幸的是,这种策略很快就会出现问题……

如果共享软件包本身并没有包装所有
Firebase在其输出中的依赖性不知道共享
代码取决于,因为您不包括或安装这些
清单。

您可以尝试将所有内容捆绑在一起,但是如果您的共享软件包
取决于您的firebase套件也取决于的东西,您现在有
代码的一部分,运行内部捆绑的副本
依赖关系和另一部分使用同样的依赖关系
软件包管理器安装的不同位置。

另外,有些图书馆真的不喜欢被捆绑在一起,在我的
包括Firebase和Google客户端库在内的经验。你
很快会发现自己试图通过
Bundler设置为了使事情正常工作。

,即使您设法完成了所有工作,您也可能是
创建大捆,然后可能导致
云功能的冷启动时间。

不是完全可靠或可扩展的解决方案。

包装和链接本地依赖关系

可以说更优雅的方法涉及包装本地
依赖性变成油粉球(类似于包装的方式
发布到NPM),并将结果复制到构建输出之前
将它们链接在更改的清单文件中。

这可以很好地工作,因为它基本上类似于您的
如果从中安装了这些软件包,Firebase代码将有效
外部域。

无论您是手动执行此操作还是编写外壳脚本以处理
事情,对我来说仍然很麻烦和脆弱,但我认为
如果您的本地依赖性很简单,这是可行的解决方法。

但是,一旦您分享了这种方法,这种方法很快就会毛茸茸
软件包取决于其他共享软件包,因为
有多个级别的包装和适应。

我的解决方案

我创建了
孤立搭配。名字
是通用的,因为它不包含firebase的任何特定的东西,
尽管我目前不知道有其他用例
输出。

它采用类似的方法
并链接依赖性,但以更复杂的方式进行。它
旨在处理不同的设置和包装管理人员,它
完全隐藏了用户的复杂性。

可以简单地将其暴露的分离株二进制
Predeploy Hook,就这样!

这也使您可以从多个不同的不同
包裹并保持配置共同分配而不是乱扔垃圾
monorepo根目录。

对于绝大多数用例来说,它应该为零

设计为与所有软件包经理兼容。

I have developed a solution and wrote an article about this. Below is an
excerpt, but here is the full
article

The problem with Firebase

When deploying to Firebase it wants to upload a folder just like a
traditional single package repository, containing the source files
together with a manifest file declaring its external dependencies.
After receiving the files in its cloud deployment pipeline, it then
detects the package manager and runs an install and build.

In a monorepo, and especially a private one, your Firebase code
typically depend on one or more shared packages from the same
repository, for which you have no desire to publish them anywhere.

Once Firebase tries to look up those dependencies in the cloud they
can not be found and deployment fails.

Hacking your way out

Using a bundler

In order to solve this you could try to use a bundler like Webpack to
combine your Firebase code with the shared packages code and then
remove those packages from the package.json manifest that is being
sent to Firebase, so it doesn’t know these packages even existed.

Unfortunately, this strategy quickly becomes problematic…

If the shared packages themselves do not bundle all of their
dependencies in their output, Firebase doesn’t know what the shared
code depends on, because you are not including or installing those
manifests.

You could try to bundle everything then, but if your shared package
depends on things your Firebase package also depends on, you now have
one part of your code running an internally bundled copy of a
dependency and the other part using that same dependency from a
different location installed by the package manager.

Also, some libraries really don’t like to be bundled, and in my
experience that includes the Firebase and Google client libraries. You
will quickly find yourself trying to externalize things via the
bundler settings in order get thing to work.

And even if you managed to make all this work, you are probably
creating large bundles which could then lead to problems with the
cold-start times of your cloud functions.

Not exactly a reliable or scalable solution.

Packing and linking local dependencies

An arguably more elegant approach involves packing the local
dependencies into a tarball (similar to how a package would be
published to NPM), and copying the results to the build output before
linking them in an altered manifest file.

This could work quite nicely, as it basically resembles how your
Firebase code would have worked if these packages were installed from
an external domain.

Whether you’re doing this manually, or write a shell script to handle
things, it still feels very cumbersome and fragile to me, but I think
it is a viable workaround if your local dependencies are simple.

However, this approach quickly becomes hairy once you have shared
packages depending on other shared packages, because then you’ll have
have multiple levels of things to pack and adapt.

My solution

I have created
isolate-package. The name
is generic because it doesn’t contain anything specific to Firebase,
although I currently don’t know of any other use-cases for isolated
output.

It takes a similar approach to what is described earlier in packing
and linking dependencies, but does so in a more sophisticated way. It
is designed to handle different setups and package managers and it
completely hides the complexity from the user.

The isolate binary it exposes can simply be added to the Firebase
predeploy hook, and that’s pretty much it!

This also allows you to deploy to Firebase from multiple different
packages and keep the configuration co-located instead of littering
the monorepo root directory.

It should be zero-config for the vast majority of use-cases, and is
designed to be compatible with all package managers.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文