Skip to content
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

Please optimize the size of libs #332

Closed
JosefJezek opened this issue Nov 24, 2017 · 120 comments
Closed

Please optimize the size of libs #332

JosefJezek opened this issue Nov 24, 2017 · 120 comments

Comments

@JosefJezek
Copy link

JosefJezek commented Nov 24, 2017

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.

@google-oss-bot
Copy link
Contributor

Hey there! I couldn't figure out what this issue is about, so I've labeled it for a human to triage. Hang tight.

@google-oss-bot
Copy link
Contributor

Hmmm this issue does not seem to follow the issue template. Make sure you provide all the required information.

@JosefJezek JosefJezek changed the title Please optimize the size of libs ❗ Please optimize the size of libs Nov 24, 2017
@jshcrowthe
Copy link
Contributor

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!

@marclave
Copy link

Anyway we can make it more modular in the form of:

import { sendVerificationEmail, reauthenticateWithCredential, ... } from 'firebase/auth';
...

etc.

@debuggingfuture
Copy link

debuggingfuture commented Jan 17, 2018

setup:

I'm trying with ES6 import as below.
The firestore import increased 300+kb to my bundle (which is even larger than the CDN version).
What are the recommended settings with webpack? Are there any example for cherry picking the imports for the most basic db operations?

import firebase from '@firebase/app';
import '@firebase/firestore';

@anjmao
Copy link

anjmao commented Jun 1, 2018

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.

@dandv
Copy link

dandv commented Sep 21, 2018

(Side note for the record, individual packages became available starting with v4.1.0 (released in May 2017)).

I'm using firebase-js-sdk only to login in user

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..

@JosefJezek
Copy link
Author

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.
https://firebase.google.com/docs/firestore/reference/rest/

@liamdanielduffy
Copy link

@jshcrowthe do you have any updates on the progress towards slimming down the bundle size, especially when working with webpack?

@Feiyang1
Copy link
Member

Feiyang1 commented Jan 26, 2019

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.
Your feedbacks are very important to us!

Thanks!

@dandv
Copy link

dandv commented Jan 26, 2019

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

@PutziSan
Copy link

PutziSan commented Jan 26, 2019

Have you already thought about a kind of mono-repo structure with different packages in the @firebase namespace (e.g. like babel)? I'm asking because the code example looks like it in principle.
A nice side effect would be that IDEs automatically import the optimized paths (e.g. with TypeScript an automatic import of firebase always ends in import * as firebase from 'firebase' and if I forget to adjust the import path, it happens again that everything is imported).

The example shown would then possibly look like this:

import { initializeApp } from '@firebase/app';
import { 
  getFirebaseAuth, 
  GoogleAuthProvider, 
  signInWithPopup 
} from '@firebase/auth';
// ...

@firebase/app would probably be a peerDependency that all other packages must have.

edit
I just realized you already have this structure. It might be useful to release these packages directly if you want to go the way of modularizing the API anyway.

@hanguokai
Copy link

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.

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).

@laurentpayot
Copy link

laurentpayot commented Jan 27, 2019

I use lazy loading of Firebase components but I get them from CDN.
For instance my loadApp function looks like this (simplified):

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 loadFirestore, loadAuth, loadUi etc.

@Feiyang1
Copy link
Member

Feiyang1 commented Jan 29, 2019

@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)?
You mentioned you have to lazily load firestore. I'm curious how you do it. Does making all operations async present any problem for you? Do you wish you can load part/all of firestore statically? What is the size limit you want to put on firestore?

@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?

@dandv
Copy link

dandv commented Jan 29, 2019

@Feiyang1,

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.

I agree, there's a lot of animation going on while the user logs in, and firebase-auth is already loaded at that point, so the slowness has got to be somewhere else. Any ideas?

@laurentpayot
Copy link

laurentpayot commented Jan 30, 2019

@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.
I was using also pretty much everything in Auth (except SAML, Github and generic OAuth providers) but I gave up building a custom UI for authentication because best practices for security and UX are evolving so fast. Thanks to FirebaseUI now I'm only mostly using the firebase.auth.Auth interface minus the SignIn-related functions. FirebaseUI, even bloated with material design light and associated fonts, is a life changer and would deserve more visibility in the Firebase ecosystem.

@hanguokai
Copy link

Some followup questions on firestore: What firestore features do you use (read/write, transaction, batch writes, realtime updates, offline persistence)?
You mentioned you have to lazily load firestore. I'm curious how you do it. Does making all operations async present any problem for you? Do you wish you can load part/all of firestore statically? What is the size limit you want to put on firestore?

@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 DB.init().then(firestore_db => {...} ) to perform all firestore operation. DB.init() load firestore.js asynchronously and init firestore instance (call settings() and enablePersistence()) only once for the first time, and return the Firestore instance. (PS: it checks some intermediate states to guarantee concurrent calls correctly). Both load firestore.js and db.enablePersistence() are asynchronous, so anyway using firestore will be asynchronous. That is no problems for me.

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.

@zevdg
Copy link
Contributor

zevdg commented Jan 30, 2019

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.

@Feiyang1
Copy link
Member

Feiyang1 commented Feb 1, 2019

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?

@codeofsumit
Copy link

codeofsumit commented Feb 2, 2019

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:

  • verifying an Access Token
  • refresh access token
  • sign in with [provider]
  • auth state change handler

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,
Sumit

@hsubox76
Copy link
Contributor

hsubox76 commented Dec 4, 2020

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.

@waleedshkt
Copy link

Yeah, noted it is a pre-alpha. But it is a pretty big thing seeing firebase-sdk getting modularized

@waleedshkt
Copy link

@hsubox76 I understand the testing stages new improved firebase-sdk has to go through yet till officially stable release.
But can you give a rough estimate for how long this testing process will take?

@dobromyslov
Copy link

@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?

@hsubox76
Copy link
Contributor

hsubox76 commented Jan 5, 2021

@hsubox76 I understand the testing stages new improved firebase-sdk has to go through yet till officially stable release.
But can you give a rough estimate for how long this testing process will take?

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.

@Tumbili
Copy link

Tumbili commented Jan 9, 2021

@HunterJoey
Copy link

https://stackoverflow.com/a/63872364/4679156

Have you test it? very interested.

@HugoGresse
Copy link

https://stackoverflow.com/a/63872364/4679156

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

@Tumbili
Copy link

Tumbili commented Jan 11, 2021

https://stackoverflow.com/a/63872364/4679156

Have you test it? very interested.

Well, it creates a separate chunk for firestore logic.
I can't say if it helps or not.

@Feiyang1
Copy link
Member

@dobromyslov you can just do npm install firebase@exp. You should be able to implement spotify login on client using firebase@exp. All required features are available.

@rondonjon
Copy link

rondonjon commented Jan 23, 2021

Hello @Feiyang1, just switched to the exp branch and I find it really promising!

Just wondering: previous releases had an accompanying firebase-admin package for the server-side; there seems to be no such package for exp (yet). Do you know if the standard package works on the server-side after when using exp?

@mimiqkz
Copy link

mimiqkz commented Jan 23, 2021

I'm following this. Can't wait to swap it out soon

@samtstern
Copy link
Contributor

samtstern commented Jan 29, 2021

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:
#4368

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.

@jacwright
Copy link

@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.

@Feiyang1
Copy link
Member

Feiyang1 commented Jan 29, 2021

@rondonjon @jacwright is right. firebase-admin is a separate package and is not covered in our exp packages.

@mmz15
Copy link

mmz15 commented Mar 6, 2021

Is this the best place to receive updates on this issue? Would be awesome to get notified once the SDK is ready.

@Feiyang1
Copy link
Member

Feiyang1 commented Mar 9, 2021

Hi @mmz15, thanks for your interest!
The new SDK is currently in alpha and you can try it now. See Sam's comment for instructions.

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.

@Feiyang1
Copy link
Member

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!

@willwillems
Copy link

The difference between firestore/lite and regular firestore using [email protected] in a semi-vanilla Nuxt (Vue.js) project. About 20KB.

firestore

@HugoGresse
Copy link

from 29 to 9kb, that's a ~70% reduction, not bad.

@laurentpayot
Copy link

laurentpayot commented May 6, 2021

But with firestore lite you’re losing offline capabilities (meaning also losing latency compensation) and snapshot listeners (to "watch" documents and queries) 😉
https://github.com/firebase/firebase-js-sdk/pull/4861/files

@samtstern
Copy link
Contributor

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:

  • Issues - if you try the new SDKs and they don't work the way you expect, file an issue!
  • Discussions - if you don't have a bug to report but just want to discuss the SDK or ask a free-form question, use a discussion. For example a Discussion would be a great place to discuss the pros/cons of firestore/lite.

Thanks for all the great thoughts so far, we're looking forward to hearing more from you all.

@firebase firebase locked as resolved and limited conversation to collaborators May 6, 2021
@Feiyang1
Copy link
Member

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!

Release notes
Upgrade guide
Reference

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests