Organize multiple functions

As you integrate Cloud Functions into your project, your code could expand to contain many independent functions. You may have too many functions to reasonably fit in a single file, or different teams may deploy different groups of functions, creating a risk of one team overwriting or accidentally deleting another team's functions. Cloud Functions offers different ways to organize your code to make it easier to navigate and maintain your functions.

Organize functions in codebases

You can use the codebase property of the functions configuration object in firebase.json to manage a large collection of functions across multiple repositories or sub-packages within a single repository monorepo setup:

 # firebase.json
"functions": {
  "codebase": "my-codebase"
  # NOTE: Codebase must be less than 63 characters and can contain only
  # lowercase letters, numeric characters, underscores, and dashes.
} 

The codebase property is supported in Firebase CLI v10.7.1 and above.

Managing multiple repositories

The codebase property can help simplify the management of multiple repositories. Let's examine a case where you have two different repositories that deploy functions to the same Firebase project:

 $  
tree  
.
├──  
repoA
│  
├──  
firebase.json
│  
└──  
functions
│  
├──  
index.js
│  
└──  
package.json
└──  
repoB  
├──  
firebase.json  
└──  
functions  
├──  
index.js  
└──  
package.json 

Without codebase annotations, the Firebase CLI would have prompted you to delete functions defined in the other repository at the time of deploy:

  $ 
  
 ( 
 cd 
  
 repoA 
 && 
 firebase 
  
 deploy 
  
 -- 
 only 
  
 functions 
 ) 
 ... 
 i 
 functions 
 : 
  
 preparing 
  
 functions 
  
 directory 
  
 for 
  
 uploading 
 ... 
  
 functions 
 : 
  
 functions 
  
 folder 
  
 uploaded 
  
 successfully 
 The 
  
 following 
  
 functions 
  
 are 
  
 found 
  
 in 
  
 your 
  
 project 
  
 but 
  
 do 
  
 not 
  
 exist 
  
 in 
  
 your 
  
 local 
  
 source 
  
 code 
 : 
         
 fn1FromRepoB 
  
 fn2FromRepoB 
  
 ... 
 ? 
  
 Would 
  
 you 
  
 like 
  
 to 
  
 proceed 
  
 with 
  
 deletion 
 ? 
  
 Selecting 
  
 no 
  
 will 
  
 continue 
  
 the 
  
 rest 
  
 of 
  
 the 
  
 deployments 
 . 
  
 ( 
 y 
 / 
 N 
 ) 
 

You can avoid this problem by adding a unique codebase annotation in the functions configuration section of the firebase.json in each project repository:

 # repoA/firebase.json
"functions": {
  "codebase": "repo-a"
}

# repoB/firebase.json
"functions": {
  "codebase": "repo-b"
} 

With codebase annotation, the Firebase CLI no longer prompts you to delete functions defined outside of your immediate repository:

  $ 
  
 ( 
 cd 
  
 repoA 
 && 
 firebase 
  
 deploy 
  
 -- 
 only 
  
 functions 
 ) 
 ... 
 i 
  
 functions 
 : 
  
 preparing 
  
 functions 
  
 directory 
  
 for 
  
 uploading 
 ... 
  
  
 functions 
 : 
  
 functions 
  
 folder 
  
 uploaded 
  
 successfully 
 #  Gleefully ignores functions from repoB 
 i 
  
 functions 
 : 
  
 creating 
  
 Node 
 . 
 js 
  
 16 
  
 function 
  
 fnFromRepoA 
  
 ( 
 us 
 - 
 central1 
 ) 
 ... 
  
  
 Deploy 
  
 Complete 
 ! 
 

Managing multiple source packages (monorepo)

The codebase property can help simplify the management of multiple source packages in a single repository. Let's examine a case where you have a firebase project directory with function definitions spread across several sub-packages:

 $  
tree  
.
├──  
firebase.json
├──  
teamA
│  
├──  
index.js
│  
└──  
package.json
└──  
teamB  
├──  
index.js  
└──  
package.json 

This setup fits the following use cases:

  • You have a monorepo setup and have different teams manage their own function definitions in an isolated package.
  • You have a function with a heavy external dependency and a long-running initialization, and want to isolate that function from other, latency-sensitive functions.

To support monrepo setup like this, define multiple functions configurations in firebase.json :

 "functions": [
  {
    "source": "teamA",
    "codebase": "team-a"
  },
  {
    "source": "teamB",
    "codebase": "team-b"
  },
] 

With this configuration, the Firebase CLI deploys functions from all packages in a single deploy command:

 $  
firebase  
deploy  
--only  
functions
i  
deploying  
functions
i  
functions:  
preparing  
codebase  
team-a  
 for 
  
deployment
i  
functions:  
preparing  
codebase  
team-b  
 for 
  
deployment
i  
functions:  
creating  
Node.js  
 16 
  
 function 
  
team-a:helloATeam ( 
us-central1 ) 
...
i  
functions:  
creating  
Node.js  
 16 
  
 function 
  
team-b:helloBTeam ( 
us-central1 ) 
...
... 

You can also deploy a specific codebase:

 $  
firebase  
deploy  
--only  
functions:team-b
i  
deploying  
functions
i  
functions:  
preparing  
codebase  
team-b  
 for 
  
deployment
i  
functions:  
updating  
Node.js  
 16 
  
 function 
  
team-b:helloBTeam ( 
us-central1 ) 
...
... 

Write functions in multiple files

When getting started with Cloud Functions you might put your first few functions in a single file:

index.js

  const 
  
 functions 
  
 = 
  
 require 
 ( 
 'firebase-functions/v1' 
 ); 
 exports 
 . 
 foo 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // ... 
 }); 
 exports 
 . 
 bar 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // ... 
 }); 
 

main.py

  from 
  
 firebase_functions 
  
 import 
 https_fn 
 @https_fn 
 . 
 on_request 
 () 
 def 
  
 foo 
 ( 
 req 
 : 
 https_fn 
 . 
 Request 
 ) 
 - 
> https_fn 
 . 
 Response 
 : 
 return 
 https_fn 
 . 
 Response 
 ( 
 "Hello foo!" 
 ) 
 @https_fn 
 . 
 on_request 
 () 
 def 
  
 bar 
 ( 
 req 
 : 
 https_fn 
 . 
 Request 
 ) 
 - 
> https_fn 
 . 
 Response 
 : 
 return 
 https_fn 
 . 
 Response 
 ( 
 "Hello bar!" 
 ) 
 

This can become hard to manage with more than a few functions. Instead, you can put all of your logic for each function in its own file and use your source file as a list of exports:

Node.js

foo.js

 const 
  
 functions 
  
 = 
  
 require 
 ( 
 'firebase-functions/v1' 
 ); 
 exports 
 . 
 foo 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // ... 
 }); 

bar.js

 const 
  
 functions 
  
 = 
  
 require 
 ( 
 'firebase-functions/v1' 
 ); 
 exports 
 . 
 bar 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // ... 
 }); 

index.js

 const 
  
 foo 
  
 = 
  
 require 
 ( 
 './foo' 
 ); 
 const 
  
 bar 
  
 = 
  
 require 
 ( 
 './bar' 
 ); 
 exports 
 . 
 foo 
  
 = 
  
 foo 
 . 
 foo 
 ; 
 exports 
 . 
 bar 
  
 = 
  
 bar 
 . 
 bar 
 ; 

Python

foo.py

  from 
  
 firebase_functions 
  
 import 
 https_fn 
 @https_fn 
 . 
 on_request 
 () 
 def 
  
 foo 
 ( 
 req 
 : 
 https_fn 
 . 
 Request 
 ) 
 - 
> https_fn 
 . 
 Response 
 : 
 return 
 https_fn 
 . 
 Response 
 ( 
 "Hello foo!" 
 ) 
 

bar.py

  from 
  
 firebase_functions 
  
 import 
 https_fn 
 @https_fn 
 . 
 on_request 
 () 
 def 
  
 bar 
 ( 
 req 
 : 
 https_fn 
 . 
 Request 
 ) 
 - 
> https_fn 
 . 
 Response 
 : 
 return 
 https_fn 
 . 
 Response 
 ( 
 "Hello foo!" 
 ) 
 

main.py

  from 
  
 fn_impl.foo 
  
 import 
 * 
 from 
  
 fn_impl.bar 
  
 import 
 * 
 

This setup assumes a project directory structure like the following:

 my-project
├── firebase.json
└── functions
    ├── fn_impl
    │   ├── __init__.py
    │   ├── foo.py
    │   └── bar.py
    ├── main.py
    └── requirements.txt 

fn_impl : Can have any name

__init__.py : Required, but can be empty

Group functions

In many projects, functions can be separated into logical groups that should be deployed and maintained together. For example, you might have a group of functions used for reporting metrics:

metrics.js

 const 
  
 functions 
  
 = 
  
 require 
 ( 
 'firebase-functions/v1' 
 ); 
 exports 
 . 
 usageStats 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // 
  
 ... 
 }); 
 exports 
 . 
 nightlyReport 
  
 = 
  
 functions 
 . 
 https 
 . 
 onRequest 
 (( 
 request 
 , 
  
 response 
 ) 
  
 = 
>  
 { 
  
 // 
  
 ... 
 }); 

You can put these functions into a group when exporting them in your index.js file:

index.js

 // 
  
 Export 
  
 both 
  
 functions 
  
 from 
  
 metrics 
 . 
 js 
  
 in 
  
 the 
  
 "metrics" 
  
 group 
 : 
 // 
  
 - 
  
 metrics 
 - 
 usageStats 
 // 
  
 - 
  
 metrics 
 - 
 nightlyReport 
 exports 
 . 
 metrics 
  
 = 
  
 require 
 ( 
 './metrics' 
 ); 

When deployed, functions will be prefixed with the name of their group, so in this example the functions would be named metrics-usageStats and metrics-nightlyReport .

When deploying functions you can limit the action to a single group:

 firebase 
  
 deploy 
  
 -- 
 only 
  
 functions 
 : 
 metrics 

Next steps

To learn more about Cloud Functions , see:

Design a Mobile Site
View Site in Mobile | Classic
Share by: