aws-amplify / amplify-ui

Amplify UI is a collection of accessible, themeable, performant React (and more!) components that can connect directly to the cloud.
https://ui.docs.amplify.aws
Apache License 2.0
818 stars 271 forks source link

useAuthenticator bundle size #3898

Open micah-redwood opened 1 year ago

micah-redwood commented 1 year ago

On which framework/platform would you like to see this feature implemented?

React

Which UI component is this feature-request for?

Authenticator

Please describe your feature-request in detail.

First off, thanks for maintaining this super helpful library.

I recently noticed that when my app loads, the vast majority of the JS is related to Amplify. I'm essentially loading an entire UI library and a ton of Amplify internals to render a single login form, over 1MB of JS!

Is there any way to use the useAuthenticator hook without loading 1MB of JS? Ideally it'd also be possible to use the Authenticator component, but at the bare minimum I should be able to use a single hook without loading all of the frontend components for the login form.

Thanks!

Please describe a solution you'd like.

Ability to import only the UI components I need, e.g. those part of Authenticator and useAuthenticator and nothing else.

There's also tons of low-hanging fruit like loading individual lodash utils instead of the entire 120kb library.

We love contributors! Is this something you'd be interested in working on?

wlee221 commented 1 year ago

Hi @micah-redwood 👋

Amplify UI components are tree shakable on modern bundlers. Do you utilize tree shaking, and what does your final bundle look like after tree shaking?

micah-redwood commented 1 year ago

Hey @wlee221 , thanks for the quick reply!

Figured it was easier to show you exactly what's going on. Here's a demo where I didn't use a single UI component, just the useAuthenticator() hook and the required provider for it. This is what we're doing in one of our apps where we just use SSO login (through a Cognito identity provider) and don't need any UI beyond a login button.

Minimal demo: https://github.com/micah-redwood/amplify-ui-auth

When I added amplify-ui, my bundle size went from 146kb to 1.52MB. That's an increase of 1.35MB. Details are in the README but I'll also include them here:

Before installing amplify-ui

Bundle size is 146kb, most of that React DOM

After installing amplify-ui

With the <Authenticator.Provider> provider and the useAuthenticator() hook, bundle size is 1.52MB

zchenwei commented 1 year ago

Hi @micah-redwood , thank you for the details! It is unlikely for bundlers to tree shake Authenticator UIs when you try to reference the Provider within the Authenticator scope by Authenticator.Provider and we do NOT recommend using the useAuthenticator hook without Authenticator UI.

If you do want to use without any UIs, I think you can reference the Provider and hook directly from @aws-amplify/ui-react-core. If you encounter any type error, it will be fixed by https://github.com/aws-amplify/amplify-ui/pull/3836 soon.

import { AuthenticatorProvider, useAuthenticator } from '@aws-amplify/ui-react-core';

That can help you drop about 300KB unnecessary Authenticator UIs and its corresponding dependencies. The bundle size will now go down to 1.21MB.

Screenshot 2023-05-08 at 11 20 40 AM

The bundle size is still big though, mainly from auth related dependencies and their dependencies such as SDKs, Cognito, etc. that are used to build the auth logic. I will transfer the issue to the team to see if they can do better tree shaking and help get the bundle size down a bit further. Thanks!

abdallahshaban557 commented 1 year ago

Hi @micah-redwood - thank you for creating this Github issue. The recommendations provided by @zchenwei will help in reducing your bundle size, and we are working now on improving the bundle size in total for the Amplify JavaScript libraries. This is one of the top items we are focusing on this year.

micah-redwood commented 1 year ago

Hey @zchenwei and @abdallahshaban557 , thanks for the quick response!

Just to give some context on why I'm using the useAuthenticator without the Authenticator UI: one of my apps is for internal users who all login via SSO (Okta). In this case, my only auth-related UI is a "sign in with Okta" button and I just need a way to know if the user is idle, logged-in or logged-out, and get their cognito attributes; no reset-password or other complex auth states that the Authenticator UI would typically manage for me.

I expect there are other "headless" use cases for this library as well, where you need to expose authentication state to your component but want to manage the UI yourself. Glad to see that this is possible with @aws-amplify/ui-react-core. Appreciate the tip!

Here's hoping whoever maintains the SDKs can prioritize reducing bundle size this coming year. I'm fortunate in that I work in the enterprise space where web performance isn't a big priority. I used to work with SEO and consumer apps, in which case I would never be able to use this library b/c it would single-handedly exceed our performance budget.

zchenwei commented 1 year ago

no reset-password or other complex auth states that the Authenticator UI would typically manage for me.

@micah-redwood That makes a lot of sense! We have to call out that though @aws-amplify/ui-react-core is a public package, it aims for internal use only and we do Not make any promise on its maintenance and SemVer contract. Sounds like your use case could simply be achieved by Auth.getCurrentAuthenticatedUser. For more API reference - https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/

reesscot commented 1 year ago

@micah-redwood As @abdallahshaban557 mentioned above, we are actively working on reducing bundle size in the Amplify JS library, which should have a big impact on the useAuthenticator size. We'll leave this open to track the impact on the UI library side of that work, but the underlying work can be tracked here: https://github.com/aws-amplify/amplify-js/issues/9817