-
-
Notifications
You must be signed in to change notification settings - Fork 357
Tree shaking #151
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
For the meantime, is there a supabase package available without realtime.js, as it increase bundle size significantly? |
@maxcodefaster you can use the client library for each components independently, but you need all for supabase-js. What's common.js? There's no significant bloat in realtime-js as far as I'm aware. |
nvm. i got an error on angular cli stating that realtime-js relies on common.js and thus increases bundle size. i forked supabase-js and remove realtime-js references, if someone is interested: https://www.npmjs.com/package/supabase-js-without-realtime-js |
@maxcodefaster , is your fork still up-to-date? |
+1 on this. Also fixes the issue of "realtime" being imported in Next.js' Edge runtime. |
I am wondering, is the new supabase v2 RC solving tree shaking? v2 distv1 distI am seeing the ability to define certain settings for const options = {
db: {
schema: 'public',
},
auth: {
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: true,
},
global: {
headers: { 'x-my-custom-header': 'my-app-name' },
},
}
const supabase = createClient(
'https://xyzcompany.supabase.co',
'public-anon-key',
options
) I am using only the database and storage function of supabase. Wouldn't it be great to allow something like: const options = {
db: true,
auth: false,
realtime: false,
}
const supabase = createClient(
'https://xyzcompany.supabase.co',
'public-anon-key',
options
) or like https://github.com/storyblok/storyblok-js#initialization does it import { databaseFeature, storageFeature } from '@supabase/supabase-js/features'
const options = {
useOnlyFeatures: [databaseFeature, storageFeature]
}
const supabase = createClient(
'https://xyzcompany.supabase.co',
'public-anon-key',
options
) |
We weren't considering tree-shaking in v2, but might in v3. That said there seems to still be some low hanging fruits here - realtime-js seems to have doubled in size 🤔 |
@soedirgo May I ask why? Supabase-js is a whopper. I'd much rather download the library on my server instead of making every single user download it in the browser. |
There are more pressing issues right now, esp. wrt functionality - once the client libs are stable enough we'll look into how to refactor them to support tree-shaking. |
@soedirgo am I right to say that the bundle size is huge since of the npm websocket package(16k) which cause the entire size to be 26kb currently. Since all browsers already support websocket, that should be easy win and fix and provide a browser build right? I would be happy to make a PR if you would consider it! |
Agreed. Most frameworks already polyfill, its supported in all major browsers and even Node JS at this point. Most React libraries already target ES6 only and tell users to polyfill. The best solution would be adding some docs about polyfilling and omitting it altogether. There is no reason for a library to provide its own polyfill imho. |
Even better if you could install each module separately. I'm trying to bundle a docker image, but This doesn't necessarily mean everyone needs to install multiple packages. I'm sure a lot of people want just the one. But it wouldn't surprise me if others are hitting this docker issue. |
Hey @mikestopcontinues, if all you use is the REST API, maybe using https://github.com/hugomrdias/postgrest-url with fetch would work for your use case! Just mentioning it since not sure what's the timeline for v3. |
Thanks @abhishiv, I ended up just creating a fork in the meantime. BTW, @soedirgo, As it stands, |
Currently Supabase takes about 300ms to be required in a AWS lambda function Being able to only require the part of Supabase could significantly decrease cold starts for many projects: |
Thanks all! Some updates on reducing the bundle size:
There's no timeline for tackling treeshaking at the moment, but we're open to proposals on how this could be done - ideally we don't have to sacrifice DX for this. |
For fetch you can use native-fetch to use the Nodejs 18 or browser native implementation when possible: https://github.com/achingbrain/native-fetch |
DX is nice, but apps are for users, not developers. Bundle size affects the user, so that should take a higher priority. DX is an extra. The deliverables are the important part. |
Here's a nice website for checking how large each part of Just click These are the current stats:
|
I couldn't agree more. It's especially frustrating when you need to handle authentication. We have auth on the landing page, which means that the whole supabase SDK needs to load the first time the user visits, just to handle auth. I really wished the supabase team would take this issue seriously and see it as a priority. @soedirgo you were asking for proposals, but I think that the original proposal is completely fine. The functions could be shorter but in essence: import { storage } from 'supabase';
storage(mySupabase).etc another way:
it could also "enhance" the supabase instance:
All proposals seem fine to me but other frameworks might already solve this in a better way. |
If you just use |
Hey all, I had this crazy idea: seeing as we know better than the compiler exactly what functionality we're using from I tried doing exactly this with For context, this is essential for me because my project is on Cloudflare workers/pages which has a very restrictive limit of 1mb max bundle size on a free plan (this means that any code included in the SSR bundle contributes to the 1mb limit). Simply adding Supabase auth functionality to my relatively barebones project was enough to stop the CF Pages deployment (mainly because of the large, unnecessary dependencies Solution:
I've only just tried this but it seems to work well and has let me bypass the 1mb CF pages limit. Disclaimer: Hasn't been rigorously tested (or tested at all, really), so use at your own risk. Final thoughts: despite ostensibly appearing to be a very hacky workaround, perhaps it's actually a decent solution because it gives the developer full control over which unused dependencies to omit without having to maintain a fork or patched version. It also doesn't seem like edit: so it turns out that sb's auth functionality is dependent on a couple of methods from the supabase postgrest class & supabase realtime class, lol. So if you're implementing auth, then the supabase postgrest package is the only package you can "strip out". Oh well, better than nothing I suppose 🤣 edit 2: While going deeper down the supabase/JS isomorphic meta-framework rabbithole, I have come across (what I think) is another important consideration for implementing treeshaking
The reason is because on the server, cross-request state pollution is a real risk. Atm it's concisely guarded against by the code in supabase-js which looks like:
This essentially ensures that a supabase client instance is never shared between requests. While the same behaviour can be replicated using only objects and ES modules (which are always singleton), it does make it easier for whoever implements a non-class based version of this lib to footgun themselves (and the community) by not providing the same guarantees on the server against cross-request contamination |
I also came across same problem. we are only using Supabase for auth. its a waste bundling everything together. Supabase need to provide a modular client side sdk like Firebase |
I think the Supabase team is reluctant to replace the classes used in the JS SDK (which is what makes the entire lib non tree-shakeable) because it would likely break the singleton pattern and its guarantees of only ever rendering a single instance of the SDK during SSR. From what I've seen, this seems to be a pattern they heavily rely on in their tutorials. In any case, the situation has become untenable for me because my framework runs middleware in a different context to the rest of the backend. Therefore, instantiating a Supabase client in middleware and server code results in the entire Supabase lib being bundled - in its entirety - twice. For my purposes, I'm planning to just rewrite the Supabase methods that my middleware relies on (e.g. Anyone foreese any issues with this approach? My only worry is whether this will necessitate rewriting the entire authentication layer. |
SB could allow you to inject each service as a plugin, so that each user could include the services they actually needed. I just forked the top-level class and removed what I didn't need. I think that's a good strategy because you can always swap back in the canonical library without any changes to your code. |
Feature request
Tree-shaking is currently not possible with the supabase-js library because
SupabaseClient
is implemented using classes. Neither Webpack or Rollup supports tree-shaking class methods.Is your feature request related to a problem? Please describe.
Supabase bundle size is quite small compared to others (firebase, amplify), but it will only increase as more features are added. Projects that do not use all the features that Supabase provides will regardless pay the cost. Firebase has realized this with their new Modular Javascript SDK.
Describe the solution you'd like
Instead of initializing a single Supabase client, here's a modular API proposal:
While this won't eliminate every piece of unused code, it's a start to enabling opt-in for specific features.
Caveats
SupabaseAuthClient
can be separated as all other modules rely on thatIf this is something you guys think is worth pursuing, I'd be happy to start working on a PR!
The text was updated successfully, but these errors were encountered: