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 LibAreporoot/functions/src/myFeatureSet2/feature2.ts, I have a CloudFunction2 by import functionB from LibBQuestions:
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.jsonimport 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.jsonunderreporoot/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 LibAVSimport * 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.