firebase / firebase-admin-node

Firebase Admin Node.js SDK
https://firebase.google.com/docs/admin/setup
Apache License 2.0
1.63k stars 370 forks source link

[FR] Bundle size #1426

Open hffmnn opened 3 years ago

hffmnn commented 3 years ago

Is your feature request related to a problem? Please describe. When using firebase-admin on AWS lambda it adds a big blog to the bundle size. We are using esbuild to bundle our sources written in TS, and bundling the admin sdk adds an extra of 5.7MB, minified 2.8MB. This is far from optimal, because the bundle should be as small as possible for better cold-start performance. The code looks like this:

import * as admin from "firebase-admin";

const app = admin.initializeApp();
console.log("app :>> ", app);

const firestore = app.firestore();
console.log("firestore :>> ", firestore);

Describe the solution you'd like Make it possible to load or install only the parts of the SDK that are really needed (like the new version of the js client sdk => https://github.com/firebase/firebase-js-sdk)

Describe alternatives you've considered I tried to add only parts of SDK we need, e.g.

import { initializeApp } from "firebase-admin/lib/firebase-namespace";

const app = initializeApp();
console.log("app :>> ", app);

const firestore = app.firestore();
console.log("firestore :>> ", firestore);

but this gives the same bundle size and it does not work, even when compiling with tsc: When running via node main.js it gives this:

/some/path/main.js:6
var app = (0, firebase_namespace_1.initializeApp)();
                                                 ^

TypeError: (0 , firebase_namespace_1.initializeApp) is not a function
google-oss-bot commented 3 years ago

I found a few problems with this issue:

hiranya911 commented 3 years ago

We are adding ES modules support and the ability to import individual modules soon. But the overall bundle size won't change anytime soon, since we plan to keep the old admin namespace and the App interface for a while. Also a lot of the bundle weight you're seeing today comes from our dependencies like @firebase/database and @google-cloud/firestore. Therefore any programs that use those services will not see a size improvement even if we did fully modularize the Admin SDK:

$ du -hs * | sort -rh | head -10
 15M    @firebase
8.0M    google-gax
6.5M    protobufjs
6.4M    @google-cloud
1.9M    @types
1.8M    node-forge
1.4M    @grpc
1.1M    firebase-admin
616K    date-and-time
524K    google-auth-library

Have you done any tests on AWS regarding cold start latency? Do you know how the bundle size of the SDK has affected its performance on AWS Lambda? At least on GCF we haven't seen any common latency issues, except in a few cases where Firestore is involved.

hffmnn commented 3 years ago

Hi and thanks for the answer. I did not explicitly test it against our setup, but various tests seem to indicate, that bundle size matter: https://mikhail.io/serverless/coldstarts/aws/ => See headline Does Package Size Matter?

I guess there are 2 things that make a difference:

And I guess the second point should make a difference?

hiranya911 commented 3 years ago

I'm not sure at 5.7MB (2.8MB minified) it makes a huge difference. Looking at the results in that article it shows a 1KB package with a cold start latency of ~0.5 seconds, and a 14MB package with a cold start latency of 1.5-2 seconds. So it may be the case that the few extra MBs added by the SDK doesn't affect the latency a lot. We'll need to run some targeted tests to know for sure.

If you're interested, please checkout #1230, which shows what our ES module entry points would look like. Although I doubt it will have any immediate effect on bundle size (please let us know if you get a chance to test).

hiranya911 commented 3 years ago

@hffmnn if you can please try out the changes in #1432 and let us know if it helps. You can checkout the PR branch and do:

npm install
npm pack

And then install the generated tarball package to your project:

npm install path/to/tarball
dhoulb commented 3 years ago

@hiranya911 Is there any long-term plan to update the Node Admin SDK to match the new v9 Javascript SDK and support tree shaking etc? It's strange that the two SDKs are now so different. Has that been considered internally and is there an intention to fix it?

It would also solve this issue.

hiranya911 commented 3 years ago

We have discussed this at length, and an effort to fully match the JS SDK is not something we want to take on. You will find some of the rationale at our modular Admin SDK alpha site: https://modular-admin.web.app/get-started/why-change (This document is somewhat outdated now, since we changed our minds about certain points during the alpha testing program. But the high-level thinking remains the same.)

The key point is that Firebase server-side SDKs (i.e. Admin SDKs) should look like GCP server-side SDKs. We also know that bundling is not a common practice in the server-side Node.js world, and size reduction in general has no significant impact on most server-side deployments -- you can typically manage the overhead via techniques like module lazy loading, which we already do. So an effort to fully treeshake the SDK doesn't even benefit most of the users. With that in mind, the modularization story for the Admin SDK is focused on delivering these:

  1. Continue to follow a style that's consistent with GCP server-side SDKs (Firestore, Storage etc).
  2. Support native ES modules, which is a feature available on Node.js 12 and up.
  3. Remove namespaces, an outdated API style in JS, and support modules with separate entry points instead.
  4. Provide some reasonable bundle size reduction via internal refactoring, for those developers that do use bundlers.
hffmnn commented 3 years ago

I tested with the new modular version and it stripes off around one MB.

IchordeDionysos commented 2 years ago

@hiranya911 Another point to consider here is the number of transitive dependencies:

Installing firebase-admin also installs 165 additional packages (mostly via Google Cloud Storage and Firestore)

Would be nice if this could be reduce, I've already files issues with @google-cloud/storage and @google-cloud/firestore.

http://npm.anvaka.com/#/view/2d/firebase-admin image

alexplumb commented 2 years ago

I'm now starting the process of upgrading Firebase from v8 to v9 and Firebase-Admin from v9 to v11 and I think it really needs to be said that the difference between the two experiences is confusing. Previously, I was able to write (almost) exactly the same code on the front-end and back-end, but now I'm forced to either write code in totally different ways OR build an adapter for the two projects.

As far as reducing bundle size, I know the difference is pretty minimal in terms of cold start performance, but surely there's an argument to be made for trigger deployment reliability. I maintain a fairly large app with quite a few triggers, and although I admit this is totally anecdotal, when the size of the bundle gets to a certain point, the triggers just stop deploying as consistently. I frequently run into errors where one of many triggers just hangs during deployment. Perhaps that's an issue with firebase-tools instead of this package, but I feel that bundle size reduction is not something that's solely in the wheelhouse of front-end packages.

Just my two cents.

laurentpayot commented 2 years ago

@alexplumb To write the same code on the front end and the back end with v9 I ended up writing a compatibility module: https://github.com/firebase/firebase-admin-node/discussions/1238#discussioncomment-682804

juniorforlife commented 6 months ago

I'm also suffering from the heavy SDK size. It makes my Vercel serverless cold start time super slow even if I use modular import. @hffmnn Have you found a way to work around this?

hffmnn commented 5 months ago

@juniorforlife Unfortunately I didn't find a workaround.