-
Notifications
You must be signed in to change notification settings - Fork 928
Please optimize the size of libs #332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hey there! I couldn't figure out what this issue is about, so I've labeled it for a human to triage. Hang tight. |
Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information. |
Hey @JosefJezek! Thanks for your interest in this! We are working on making the SDKs easier to consume for mobile networks but nothing currently to report here. I will keep this issue open and will update as the situation improves! |
Anyway we can make it more modular in the form of:
etc. |
setup:
I'm trying with ES6 import as below.
|
I'm using firebase-js-sdk only to login in user and getting his tokenId, later I pass this token to my api proxy so I can do other operations in backend. It would be great to at least reduce auth module bundle size first. |
(Side note for the record, individual packages became available starting with v4.1.0 (released in May 2017)).
I would second the request to optimize the size of the auth solution, since this would be a great onboarding path for many developers. Authentication is hard, and getting it right using Google's security is a smart choice. However, the minimum bundle size for signing up a user with the Firebase Web UI and federated identity providers is huge:
That's 411kB (120kB gzipped) just to log users in. This comes pretty close to the performance budget Google recommends for mobile. One immediate optimization would be load Firebase UI only when the user is not logged in, using Dynamic imports or an equivalent. Dynamic imports have been supported since 2019 in all major browsers.. |
Temporary solution for Firestore is described in this article https://davidea.st/articles/firebase-bundle-size Instead of Server Side Rendering we can use Firestore REST API and PRPL-50. |
@jshcrowthe do you have any updates on the progress towards slimming down the bundle size, especially when working with webpack? |
Hi Guys, I want to provide some updates on what we are thinking about the size optimization. We had a lot of discussion about it recently. While it’s not completely settled, I can share some ideas we have discussed. At the root of the issue, firebase components expose the entire API surface in the component instance. For example, all Firebase Auth APIs hang off the firebase.auth() object. Bundlers can’t tree shake them because they can’t be statically analyzed. To solve the problem, we need to export functions/classes as top level module exports to expose the APIs, so you can explicitly import what you need. For example: // today
import * as firebase from 'firebase/app';
import 'firebase/auth'; // import the entire component
const app = firebase.initializeApp({});
const provider = firebase.auth.GoogleAuthProvider();
app.auth().signInWithPopup(provider).then(user => {...}); // future
// This is just an example to illustrate the idea and the final syntax
// is not going to look exactly like it
import { initializeApp } from 'firebase/app';
import {
getFirebaseAuth,
GoogleAuthProvider,
signInWithPopup
} from 'firebase/auth'; // import functions individually.
const app = initializeApp({});
const auth = getFirebaseAuth(app);
const provider = new GoogleAuthProvider();
signInWithPopup(auth, provider).then(user => {...}); Just to clarify, this is just an example to illustrate the idea. The functions and their names are likely to be different in the final product. Besides the API changes, we also have a lot of work to do to refactor the implementation in order to decouple components and separate interconnected logics, otherwise you might run into a situation where you import just a few symbols but end up pulling in 80% of the codebase. It’s a big change for Firebase. The API is going to look completely different and we may need to rewrite a large part of the codebase, so it’s going to take some time before we can present it to you. We also realize it’s a very disruptive change to firebase developers, so we want to hear your voice about it as early as possible. Finally we’d like to learn more about your use cases. What product/feature do you use? What do you wish you could exclude from your bundle? Do you have a use case where you want to load some firebase features at the startup and load more features later? Please leave the comment below. Thanks! |
One "gateway" use case for the JS SDK is authentication. Very hard to get right on your own, and much easier to leverage Google's infrastructure and security. The problem I've run into is that social login is a lot slower than with other systems. Try to log in with GitHub in the Firebase demo, and by comparison at https://spectrum.chat/login More at firebase/firebaseui-web#511 |
Have you already thought about a kind of mono-repo structure with different packages in the The example shown would then possibly look like this: import { initializeApp } from '@firebase/app';
import {
getFirebaseAuth,
GoogleAuthProvider,
signInWithPopup
} from '@firebase/auth';
// ...
edit |
My app loads firebase app and auth js at the startup to get user's login state and profile. Other firebase services are loaded lazily when needed, especially firestore js is too big that must load lazily(this lead to all related operations are async). All firestore operations and some cloud functions are only for logged in users, so firebase auth is loaded at the startup. Firebase app+auth is 190KB, hope it less than 50KB. For firebase auth, I only used one provider(Google) to login(by token) and logout, all other auth methods are disabled. In addition, hope auth return cached login state at once at the startup when online, rather than wait login state from firebase backend(it usually waits 2-3 seconds). |
I use lazy loading of Firebase components but I get them from CDN. let app = null
export loadApp = () => app || app = new Promise( (resolve, reject) =>
document.body.appendChild(Object.assign(document.createElement('script'), {
src: `https://www.gstatic.com/firebasejs/${FIREBASE_VERSION}/firebase-app.js`
onload: () => resolve(firebase.initializeApp(config))
onerror: reject
}))) Same for |
@dandv Thanks for sharing your story! I'm not sure if the lib size is the main cause of the slowness you experienced, but we understand Auth is a very important use case for users. Auth is going to be a big focus of this effort and we hope this redesign leads to a much smaller auth footprint in your bundle, so your app loads much faster. @PutziSan Yes! we already have scoped @firebase/{component} packages. We don't have any plan to change it with the redesign. We will continue to have the all in one firebase package as well since it provides a convenient way to get all firebase services that are compatible with each other. @hanguokai Thanks for sharing your use case! Our goal is making it possible to include only what you need in your bundle. Since it looks like you use only a small set of auth functionalities, app + auth can be a lot less than 190KB after tree shaking. Some followup questions on firestore: What firestore features do you use (read/write, transaction, batch writes, realtime updates, offline persistence)? @laurentpayot Thanks! I assume you did this because of the size of firebase. Would you consider bundling firebase in your app statically if you can include only what you use? What features do you use for Auth and Firestore respectively ? What is your standard on size? |
I agree, there's a lot of animation going on while the user logs in, and |
@Feiyang1 thanks for caring about the size of Firebase. This is an issue that concerns all developers using Firebase products as well as end users. My standard on size is whatever can keep my PWA lighthouse performance indicator in the green zone, as recommended by Google. I'm using SSR to have better first contentful/meaningful paint metrics, but I also need to be interactive as fast as possible. I agree that "size matters" but parsing all that Firestore JS also has a high impact on the main thread. I had to use the above lazy loading trick to have finer timing control so I can delay download+parsing to the actual use of Firebase features instead of when the module is loaded. Even if I use chunks and tree shaking (Rollup bundle), will building Firebase in my app statically with only needed features really help performance-wise knowing that my app is a SPA and thus most modules are loaded at the beginning? I'm using pretty much everything in Firestore, except GeoPoint for now. |
@Feiyang1 For firestore, I use read/write, batch delete( to clear all resources), and offline persistence with multiple tabs support. Multiple tabs are the essentials of the web, you can not ask user to only open one tab. So I use experimentalTabSynchronization option. I sync firestore data periodically, rather than use realtime updates, because the app is only for one user with multiple devices. Offline persistence feature with multiple tabs support is good, but the default offline behavior maybe overwrite user's data if there is a conflict (like source code version control). So I implement sync(pull or push) method instead of read/write. Depends on the data types, sync method may auto merge data or resolve conflict by user manually. (PS: The logic of sync is a little complicated since many edge cases need to be considered) I use the code like I don't know what firestore features can be split. But if there a smaller libraries can fit my needs I will use it. Currently I use read/write/batch delete/query all(for a collection) and offline persistence. Except tree shaking, I hope firebase can supply a custom building method for selected features to generate smaller libraries. |
As most others on this thread, I'm most concerned with auth and after that, firestore. For most pages on my app, I need to know if the user is logged in or not before displaying any meaningful content. If they aren't logged in, then I can paint the log-in prompt immediately, but I also lazily load firestore and display non-sensitive information when it finishes loading. In this scenario, loading the auth quickly is most important, but the info coming from firestore might also be important. For example, if someone's friend sent them a link to my site, they might be uncomfortable creating an account until they see their friend's avatar. If it takes too long to load, a conversion is lost. If the user is already logged in then I can't really paint anything meaningful until firestore is loaded, but in theory, this should be less of a problem due to service worker. The large bundle size isn't great for my user's mobile data caps in any case, but it only affects load time before the service worker is installed, and that is almost always before the user has logged in. |
Thank you all for the amazing use cases! @dandv TBH I couldn't say without looking into the details and I'm no expert in firebaseui. Sorry! @wti806, Do you have any idea? @laurentpayot If you use most features from firestore/auth and want to keep the app light, you probably still need to do some kind of lazy loading. What the proposed APIs enable you to do is to lazy load in a more granular fashion instead of at the entire component level. For example, you can include just read/write from firestore in your main bundle, so you can have a fast first paint with meaningful data while still keeping your main bundle small and lazy-load realtime updates or offline persistence. @hanguokai Thanks so much for sharing the detailed user journey, really appreciate it! I like the idea of creating custom build. I think the proposed APIs can help you achieve it. You can pick the firebase features you need and import just them. If it is small enough, you may include it in your main bundle, otherwise you can create a separate chunk and load it lazily. Do you think it's something that would work for you? |
Ho FB Team, wanted to give my quick notes to you. I’m currently building Geoman.io with it. Size is a problem, yes. We started to abstract Firebase away in our own API to get rid of the firestore module on the frontend. At some point, we only had it in to generate the unique firebase document keys. Would be nice to have that feature modularized. I lazy load most modules by bundling them in async components that get loaded when needed so initial page load isn’t hit that hard. However, auth is in there. FirebaseUI is only loaded when the user clicks on “sign in”. Regarding Auth we would love to have the following functions available as separate imports:
I appreciate that you recognize the size problem and start with this change 👍. Providing a few basic functions as a separate import would be already a nice first step, like generating a new document ID for firestore. Best, |
Just to be clear, the exp packages are not officially released even in alpha. The versions being published right now are primarily meant for internal testing. If you use them right now, many things (possibly entire products) could be broken, and we aren't offering any support yet. We hope to begin offering it for limited testing in a few weeks and will have a sign-up form for those who want to help test. Even when the trial is open, we want to emphasize the exp packages are experimental and should not be used in production at all until GA. |
Yeah, noted it is a pre-alpha. But it is a pretty big thing seeing firebase-sdk getting modularized |
@hsubox76 I understand the testing stages new improved firebase-sdk has to go through yet till officially stable release. |
@Feiyang1 thank you for the TypeScript code base. I'm looking forward for comprehensive signInWithPopup() with custom OAuth providers and redirect resolvers support to implement custom auth like described here https://github.com/firebase/functions-samples/tree/master/spotify-auth How can I install firebase@exp? Is it available only from the sources? |
We're working hard on this but as a rule we don't provide timelines. We will have an alpha as mentioned above, and we will post here when the alpha is ready for testing, with directions on how to sign up. |
Have you test it? very interested. |
this is not very useful, the first render will be sooner, but if your app still depends on firestore to load any data, you'll need to load firestore nonetheless, and the app size will so not be smaller |
Well, it creates a separate chunk for firestore logic. |
@dobromyslov you can just do |
Hello @Feiyang1, just switched to the Just wondering: previous releases had an accompanying firebase-admin package for the server-side; there seems to be no such package for |
I'm following this. Can't wait to swap it out soon |
Well ... the moment you've all been waiting for is here! We're now ready to invite you all to check out the Alpha release of our new smaller SDK! This issue has all the details: If you're interested just fill out the form and then we'll send you an email with all the details as soon as we can. Remember this is an alpha SDK so it's not ready for prime time in your production apps, but it's ready for you to experiment with and let us know what you think! We truly need your help to make sure this SDK can move from Alpha to Beta to fully stable so that you can all build great, lightweight Firebase apps. |
@rondonjon I believe the firebase-admin package is not being worked on since it is used server-side and library size is not as critical on the server as those being delivered over the network. Correct me if I am wrong. |
@rondonjon @jacwright is right. |
Is this the best place to receive updates on this issue? Would be awesome to get notified once the SDK is ready. |
Hi @mmz15, thanks for your interest! Are you looking for when the SDK will be officially launched? For that, I recommend following our release notes. We will update the thread as well (to finally close it) :) All discussions for the new SDK happens here. |
Hi all We are pleased to announce that the version 9 of the Firebase JS SDK is now available in beta! 🎉🔥 Version 9 is fully modular and tree shakable, so I think we can finally close this issue. Some more info: Read here on how to upgrade from version 8 to the modular SDK and learn more about version 9 here. You can also access the setup page and API Reference to get started. Please continue to tell us what you like and don’t like on GitHub Discussions. If you encounter any bugs, file them on GitHub Issues. We look forward to showing you more about this at Google I/O May 18-20. To register for I/O, see here. Cheers! |
The difference between |
from 29 to 9kb, that's a ~70% reduction, not bad. |
But with firestore lite you’re losing offline capabilities (meaning also losing latency compensation) and snapshot listeners (to "watch" documents and queries) 😉 |
Hey everyone! There are 50-100 people watching this issue receiving every update as an email, so I am going to lock the discussion (actually this may be the most watched issue on all of Firebase's GitHub repos). But that doesn't mean we want to stop talking about this issue! We really appreciate your enthusiasm about our newer, smaller SDKs and we absolutely want to hear from you more. So let's move future discussions to one of two places:
Thanks for all the great thoughts so far, we're looking forward to hearing more from you all. |
Hi all, 9.0.0 has been officially released! It is tree-shakable, so you will be able to remove unused code from Firebase. It also comes with a set of compat libraries to make the upgrade easier. If you encountered any problem upgrading/using the new version, please open an issue as always! |
Could you optimize the size of libs? We have limit ~ 50 KB per route on 3G mobile networks. :-/
Check out the video Measure Time to Interactive.
The Cost Of JavaScript is high.
The text was updated successfully, but these errors were encountered: