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

RFC: Amplify Library Modularization and Bundle Size Improvement #3365

Closed
powerful23 opened this issue May 30, 2019 · 53 comments
Closed

RFC: Amplify Library Modularization and Bundle Size Improvement #3365

powerful23 opened this issue May 30, 2019 · 53 comments
Assignees
Labels
feature-request Request a new feature

Comments

@powerful23
Copy link
Contributor

powerful23 commented May 30, 2019

This issue is a Request For Comments (RFC). It is intended to elicit community feedback regarding a proposed change to the library. Please feel free to post comments or questions here.

Situation

The bundle size of amplify-js has always been a concern to the customers. At the very beginning we put all the categories in a single package which leads to a huge bundle size. Then we decided to split the whole package into several ones based on the category so we can import each category on need.

The Problem

Although the bundle size can be largely reduced by using scoped packages instead of directly using aws-amplify, there are still many things that we can do to make it better:

  • The way of using scoped packages is tricky and not intuitive.
  • When using aws-amplify-react, all the Amplify library will be imported and bundled regardless of the actual usage.
  • Using default export is not the best practice.
  • Graphql will be imported when using API module which is unnecessary if only calling REST APIs.
  • Version conflicting when using scoped packages which will lead to multiple versions of same package under node_modules
  • The aws-sdk takes a lot of the space in the bundle size but we are only using part of it.

Proposed Solutions

  • Generate ES6 modules so that bundlers like Webpack and Rollup can do the tree shaking when importing something from aws-amplify. So instead of using scoped packages like import Auth from '@aws-amplify/auth' you can now just use import { Auth } from 'aws-amplify' and the bundler will do the rest work for you.
  • Update the library code and the documentation to stop using default import/export but also keep backward compatibility.
  • Split the API module into two, one will be only for REST APIs, the other one will be for GraphQL APIs. For example, import { RestAPI, GraphQLAPI } from 'aws-amplify'
  • Use peer dependencies and loose version number to avoid version conflicting.
  • Build a http client to replace aws-sdk. The client should be able to generate the request context, sign the request with AWS credentials, validate the input parameters, configure the retry policy etc.

Related Issues

#122
#2781
#3097
#3096
#2309
#2199
#1831
#701
#2894
#2058
#488

Reference

Thanks to @aldo-roman for the working of #2313

Preview Versions

05/31/19

You can now use the preview version of amplify to test:

npm install aws-amplify@preview

The preview version has generated the ESM modules for all the categories so for example, if you are using webpack 4 bundling your react app, and you are only using Auth module like:

import { Auth } from 'aws-amplify';

Auth.signIn();

Then only the Auth module will be included in the bundle. Note that the tree shaking will only happen under the production mode.

@powerful23 powerful23 changed the title RFC: Amplify Library Modularization RFC: Amplify Library Modularization and Bundle Size Improvement May 30, 2019
@powerful23 powerful23 pinned this issue May 30, 2019
@tuhinkarmakar
Copy link

tuhinkarmakar commented Jun 3, 2019

I tried the preview versions with my Angular app. The reduction in bundle size was significant. However the setup process wasn't easy. I had to go through a lot of trial and error to make it work.

Steps

  1. Import the modules from the aws-amplify package in main.ts
  2. Configure the modules individually i.e. Auth.configure(config)
  3. Register the module with the Amplify module using Amplify.register(Auth)
  4. Add the AmplifyService to your root module as { provide: AmplifyService, useFactory: () => AmplifyModules({ Auth })
  5. Emulate the process object
  6. Install @types/zen-observable

@powerful23
Copy link
Contributor Author

@tuhinkarmakar Hi, thanks for testing! I think Step 1, 2, 4 are required but Step 3 is not. Do you have any issue if not calling Amplify.register()?

@tuhinkarmakar
Copy link

tuhinkarmakar commented Jun 4, 2019

@powerful23 Without step 3, I was getting an error saying No Auth module registered with Amplify. I updated my comment to add 2 more steps that were required.

@mydea
Copy link

mydea commented Jun 5, 2019

Even when just pulling in @aws-amplify/auth, it adds ~80kb of gzipped size. That does feel pretty extensive for just handling authentication. (See https://bundlephobia.com/result?p=@aws-amplify/auth@1.2.24, which also matches what I can see in my app). Are there any plans (or ways) to reduce this? It seems that almost 50% of this is aws-sdk. Is there no way to use Cognito without adding on 270kb (un-gzipped) of JS to your app?

@aldo-roman
Copy link
Contributor

@mydea it seems aws-sdk is publishing only on UMD and, thus, does not support tree-shaking. So i guess it is not possible with current status of the library. They should go through a similar work proposed on this issue. See aws/aws-sdk-js#1766

@nihakue
Copy link

nihakue commented Jun 6, 2019

Does this: https://aws.amazon.com/blogs/developer/new-aws-sdk-for-javascript-developer-preview/ influence the need for writing your own http client? If you can import just the parts of the sdk you need, you can significantly reduce the bundle size.

@mydea
Copy link

mydea commented Jun 6, 2019

If I try to force using aws-sdk@preview it just gives me 2.329 and it remains the same output size!

@mainawycliffe
Copy link

mainawycliffe commented Jun 8, 2019

Impressive, just shaved off around 500K from 1.68 to 1.17, still this library is taking between 30 - 35% of the remaining 1.17 and i only need Authentication. I am using the preview of Angular.

I see the auth angular components inside the final bundle and am not using them, i have my own custom components. And they are occupying a whooping 5% on their own. For some tree shaking is not removing them for some reason.

@ahallora
Copy link

Split the API module into two, one will be only for REST APIs, the other one will be for GraphQL APIs. For example, import { RestAPI, GraphQLAPI } from 'aws-amplify'

Yes!! 🚀🙌😄

@jadbox
Copy link

jadbox commented Jun 18, 2019

I must echo @ahallora, GraphQL is one of the largest bundled packages in production app... yet we don't use it at all. It's a massive tax when using aws-amplify to the point where we're considering forking @aws-amplify/api just to strip it out.

@jadbox
Copy link

jadbox commented Jul 2, 2019

@powerful23 thought I'd link your PR here for splitting the API and Graphql features:
#3362

@roborourke
Copy link

This shaved off 180kb from my bundle of just analytics and auth but it's still 400kb in total. Would love to see the modularised AWS SDK used in this preview version.

@jadbox
Copy link

jadbox commented Jul 4, 2019

I only use auth, but this branch still pulls in Analytics in my build unfortunately.

@jadbox
Copy link

jadbox commented Jul 10, 2019

@powerful23 is there plans to keep the preview tagged release in-sync with the updates happening in stable? I think the current preview is two releases behind the stable version currently.

@roblangridge
Copy link

roblangridge commented Jul 11, 2019

I'm on 2.0.0-preview.1, using WebPack 4.35.3 and only using Auth & Analytics, when i do:

import { Analytics } from "aws-amplify";

i still get GraphQL, PubSub and all of aws-sdk

Screenshot 2019-07-11 at 20 34 57

@powerful23
Copy link
Contributor Author

@jadbox @roblangridge are you running the app in the production mode?

@roblangridge
Copy link

@powerful23 yes, with mode: "deployment" things are looking like this:

Screenshot 2019-07-11 at 21 09 37

@jadbox
Copy link

jadbox commented Jul 12, 2019

@powerful23 not sure what you mean by "production mode", but building with CRA via "npm build" is what I'm using, while setting NODE_ENV to production.

I can still confirm that graphql is being bundled even though I'm not importing it or any libs that use it:
19-07-12-09-16

If need be, I can get you access to my project for testing (jdunlap AT outlook.com).

@powerful23
Copy link
Contributor Author

@jadbox I think you need to configure your webpack config to add mode: "production" in it. https://webpack.js.org/guides/production/#specify-the-mode

@aldo-roman
Copy link
Contributor

@jadbox or better yet, how are you building? If you are using create-react-app then just running npm run build activates de production mode. But this may not be the case if you have a manual webpack.config.js or some other bundler.

@davidmold
Copy link

It's really great, but seems poorly documented, that if you just want the Auth module, and you do this:

import Auth from '@aws-amplify/auth'

You save nearly 600K on your build over doing this:

import { Auth } from 'aws-amplify'

@jadbox
Copy link

jadbox commented Jul 22, 2019

@powerful23 @aldo-roman sorry for the delay, I am building in production mode (via create-react-app). All my imports are in the style of import { Auth } from 'aws-amplify'.

Using react-scripts v3.0.1 and aws-amplify: 2.0.0-preview.1

@hgl
Copy link

hgl commented Jul 26, 2019

I'm having difficulty bundling aws-amplify with rollup, encountering the exact same error described in aws/aws-sdk-js#1769 (comment)

I think because aws-sdk v2 isn't published as es modules.

Could aws-amplify depend on v3 instead v2 to make it be more friendly to modern bundler like rollup?

@roborourke
Copy link

I've ended up rolling my own analytics and auth script using the v3 sdk as I wasn't really using any other parts of amplify. Good news is that bundle is a 35kb download. It's part of a WP plugin right now but I'll see if I can extract it out as an npm package.

@hgl
Copy link

hgl commented Jul 26, 2019

@roborourke how do you roll your own auth with v3 sdk? afaik, the only relevant package is client-cognito-identity-browser, and it only lets you manage the user pool & identity pool but not the actual authentication?

@roborourke
Copy link

@hgl you call GetId which requires no auth, then GetCredentialsForId with that ID. Then you can use those credentials for calling the PutEvents and UpdateEndpoint pinpoint commands

@bezreyhan
Copy link

bezreyhan commented Mar 3, 2020

Thanks for prioritizing this change. We are currently using @aws-amplify/auth and it is adding 311kb minified / 74kb gzipped. This is way bigger than our app can afford. Two questions:

  1. Do we have an ETA for when the modularization will be finished?
  2. Any idea what the new bundle size will be?

Alternatively, we've been thinking about migrating to using amazon-cognito-identity-js, which is 14kb gzipped. If we are just using @aws-amplify/auth, what is the biggest down side to migrating to amazon-cognito-identity-js?

@jliebrand
Copy link

Any update on (a) when this will be merged in to the main release, and (b) when GraphQL will be removed from those needing only the API ?

@sammartinez
Copy link
Contributor

Hey everyone, wanted to provide an update of the Modularization work, we currently heads down on this in order to deliver this feature in the coming weeks. Will provide an update on this next week for you. Thanks!

@Amplifiyer
Copy link
Contributor

Amplifiyer commented Mar 12, 2020

@depiction, @jliebrand and @bezreyhan, we are in our final phase of testing the new modularization release and is available for you to test as well using preview tag. Can you try testing that release in the meantime and let us know if you face any issues?

@bezreyhan
Copy link

bezreyhan commented Mar 13, 2020

@depiction, @jliebrand and @bezreyhan, we are in our final phase of testing the new modularization release and is available for you to test as well using preview tag. Can you try testing that release in the meantime and let us know if you face any issues?

I'm using @aws-amplify/auth. What would be the best way to test out the preview tag?

Update
Using the preview tag I imported the Auth library: import { Auth } from 'aws-amplify'; I also tried import Auth from '@aws-amplify/auth'; using "@aws-amplify/auth": "1.2.27-preview.106".

It looks like the Auth module is 31kb and the aws-sdk is 10.71kb. This is a huge improvement over the 74kb I was seeing before. Thanks for making these changes!

From my initial testing, login, logout, and sign up all worked as expected.

I'm wondering if there is a way where we could make the Auth module even lighter. Even with these changes, the Auth module is our largest dependency.

@Amplifiyer
Copy link
Contributor

I'm using @aws-amplify/auth. What would be the best way to test out the preview tag?

You can use the npm preview tag as yarn add @aws-amplify/auth@preview All the current published tags for aws-amplify can be seen here

@Amplifiyer
Copy link
Contributor

Amplifiyer commented Mar 19, 2020

Modularization is available in Preview

Hi all,

With us launching Modularization in the coming weeks, we wanted to provide the ability for you to use our current preview tag (https://www.npmjs.com/package/aws-amplify) in order to start using Modularization within your applications. We highly recommend to not use this preview tag in production as we are still in the process of fixing small bugs and validating with our own testing internally.

Breaking Changes:

Below is a breakdown of the breaking changes that are coming with v3 that we wanted to make you aware of:

  • AWS.credentials and AWS.config don’t exist anymore anywhere in Amplify JS
    • Both options will not be available to use in version 3. You will not be available to use and set your own credentials. Migration plan on “How to migrate to using Amplify provided credentials” will follow in the coming weeks after GA launch.
  • v2 of AWS SDK JS is not vended as part of Amplify JS. If you rely on v2 of AWS SDK JS, you will need to export it separately. Since AWS SDK JS v3 is exported modularly, only AWS Services that Amplify JS currently supports will be available in v3.
  • If you are using exported paths within your Amplify JS application, (e.g. import from @aws-amplify/analytics/lib/Analytics this will now break and no longer will be supported. You will need to change to regular import statements.
  • If you are using categories as Amplify.<Category>, this will no longer work and we recommend to import the category you are needing to use.
    • The one exception to this is using aws-amplify-angular package where we are still supplying all instantiated categories. This is subject to change in a later release.
  • For aws-amplify-react for the Authenticator Component, you will need to import the styles yourself.
    • You will need to import the following: import '@aws-amplify/ui/dist/style.css';

Installing preview-tag:

For installing Amplify modules:

You are able to install by running yarn add @aws-amplify/<category>@preview. E.g. yarn add @aws-amplify/auth@preview if you are using the Auth Module.

For installing aws-amplify:

You are able to install by running yarn add aws-amplify@preview

For installing UI Components:

You are able to install by running yarn add aws-amplify-<framework>@preview. E.g. yarn add aws-amplify-react@preview if you are using our React UI Components.

NOTE: Please delete your existing node_modules before installing as there are some conflicts with the older versions of package.

Filing Bugs:

If you do find issues, please let us know by cutting us a bug and we can look into the issue.

Thank You!
Amplify JS team

@0xdevalias
Copy link

0xdevalias commented Mar 20, 2020

Not sure if actually a bug, or my own issue. Can you provide a minimal example of how to use withOAuth to use the Cognito hosted login?

Edit: So I think my issue was that I separately installed each dependency:

yarn add aws-amplify@preview
yarn add aws-amplify-react@preview

Rather than doing them together:

yarn add aws-amplify@preview aws-amplify-react@preview

Since it worked after I did it again the latter way.

Old post details

This is what I have, and but I get a pile of 'cannot import' type errors. Installed both with the @preview version, and deleted my node_modules first:

yarn add aws-amplify@preview aws-amplify-react@preview

It wasn't mentioned above, but do we also need to add all of these (based on what we want to use)? Or should they all just come 'as part of it'?

warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/analytics@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/api@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/auth@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/core@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/interactions@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/storage@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/ui@^2.0.0".
warning " > aws-amplify-react@2.3.11-preview.123" has unmet peer dependency "@aws-amplify/xr@1.1.5".
"aws-amplify": "^1.1.31-preview.110",
"aws-amplify-react": "^2.3.11-preview.123",
import { Auth } from 'aws-amplify'
import { withOAuth } from 'aws-amplify-react'

Auth.configure({
  // REQUIRED - Amazon Cognito Region
  region: 'us-east-1',

  // OPTIONAL - Amazon Cognito User Pool ID
  userPoolId: 'us-east-1_REDACTED',

  // OPTIONAL - Amazon Cognito Web Client ID (26-char alphanumeric string)
  userPoolWebClientId: 'REDACTED',

  // OPTIONAL - Enforce user authentication prior to accessing AWS resources or not
  mandatorySignIn: false,

  // Cognito Hosted UI configuration
  oauth: {
    domain: 'REDACTED',
    scope: ['email', 'profile', 'openid'],
    redirectSignIn: 'http://localhost:3000/',
    redirectSignOut: 'http://localhost:3000/',
    responseType: 'code', // or 'token', note that REFRESH token will only be generated when the responseType is code
  },
})

image
(etc)

@Amplifiyer
Copy link
Contributor

Hi @0xdevalias, there shouldn't be any difference between installing both the packages in one command or separately, it seems that aws-amplify-react package was installed the preview version but somehow aws-amplify was reverted or still using the non-preview version. Let us know if you are able to reproduce it again.

@imedadel
Copy link

@Amplifiyer can I suggest one more thing? Moving aws-sdk to peer dependencies :)

@Amplifiyer
Copy link
Contributor

@imedadel Do you mean aws-sdk version 2.x or the new aws-sdk-js-v3? We have completely removed the dependency on aws-sdk version 2.x and only depends on aws-sdk-js-v3. I'm not completely convinced that moving that to peer dependency is better mostly because currently the whole Amplify library extensively depends on it and have strict requirements on which version to use.

Since peer dependencies don't help in reducing the application bundle size but only library's bundle size which is mostly irrelevant (that's my understanding, happy to be convinced otherwise).

@Amplifiyer
Copy link
Contributor

Closing this RFC as all the proposed solutions have been launched, see https://aws.amazon.com/blogs/mobile/amplify-framework-announces-new-rearchitected-ui-component-and-modular-javascript-libraries/

Thank you everyone for great feedback and all the contributors for making this happen.

@github-actions
Copy link

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request Request a new feature
Projects
None yet
Development

No branches or pull requests