Background: I have about 20 Firebase Cloud Functions and they are stored under the default reporoot/functions/src/
folder, which was created when I first init the Firebase project. Each Cloud Function could have its own unique dependencies and all are specified inside one single reporoot/functions/package.json
Simplified version of the scenario:
package.json
, I specify dependencies LibA, LibB and devDpendencies LibXreporoot/functions/src/myFeatureSet1/feature1.ts
, I have a CloudFunction1 by import functionA from LibA
reporoot/functions/src/myFeatureSet2/feature2.ts
, I have a CloudFunction2 by import functionB from LibB
Questions:
reporoot/functions/src/myFeatureSet1/feature1.ts
?package.json
under reporoot/functions/src/
? Or the deployed Cloud Function will have only what it needs without extra dependencies included?package.json
under reporoot/functions/src/
? I think deploying the Cloud Function associates npm i --production
and hence will not include devDependencies. Is that true?package.json
files for different codebase. But following that leads to the following error when I start using the emulator:
functions: Failed to load function definition from source: FirebaseError: Error parsing triggers: Cannot find module 'axios'. Note: One of my Cloud Function uses axios and I put it inside one package.json
import functionA from LibA
VS import * from LibA
?The following assumes your index.ts
is similar to:
export functionA from LibA
export functionB from LibB
and each function is similar to:
export default functions.https.onRequest(/* ... */);
- If I deploy CloudFunction1 to Firebase, will LibA, LibB and LibX be packaged together in the same deployment zip?
As LibA and LibB are true dependencies, they will be installed when deployed. As LibX is in devDependencies
, it will be skipped.
However, if the source code of LibA, LibB and LibX are all inside the reporoot/functions
folder, they will all get deployed, but not necessarily executed (that would depend on your code).
- Will the number of dependencies impact the cold start time of all functions developed with the same
package.json
underreporoot/functions/src/
? Or the deployed Cloud Function will have only what it needs without extra dependencies included?
By default, dependencies will affect the cold start of all functions.
There are some ways you can structure your code to mitigate this, as covered in this article, this thread or by using a library like better-firebase-functions
.
You could also compile your code into many bundles, deploying a single bundle of each function, containing only that function and its dependencies. You'd do this using deploy scripts similar to those covered in this thread. This strategy can get messy if not properly thought out.
- Similar to the Question 2 above, how about devDependencies?
As deployed functions are considered a production environment, you are correct in that devDependencies
will not be installed in the production environment.
- How can I split the dependencies among different functions so that each function packages with only the required dependencies?
One of the best approaches to achieve this is to export each function in its own functionX.ts
file (preferably with an accurate name). You can then compile these as standalone bundles, invoke them using lazy loading or group them together with other similar functions. See the resources linked above for further details.
If axios
is used by only one function, either spin that function off into its own file/bundle or import it using (await import('axios')).default
when you need it. The error you get suggests that one of your libraries tries to import the axios
library at the top of the file, but when that library gets imported by a non-axios
function (where it's omitted from the package.json
file), it causes a deploy error.
I would personally use either node-fetch-native
, node-fetch
or gaxios
(a node-fetch
-based variant of the axios
APIs, used internally to the Firebase libs) instead.
- Will there be any code start time difference if I
import functionA from LibA
VSimport * from LibA
?
Based on just that line, it's hard to tell. It would depend on the contents of your library and the build tool you are using. The default compiler will just convert your TypeScript to plain JavaScript regardless of whether its used or not. Whereas if your build tool supports "tree shaking", it will only compile what it needs ignoring the unnecessary "leaves" (unused code). Popular tree shaking tools include Webpack and Rollup.