Search code examples
vue.jswebpackaws-sdknuxt.jsaws-amplify

How can I reduce the webpack bundle size for a Vue.js / Nuxt.js project incorporating AWS SDK?


Summary:

I have created projects, with Vue.js and Nuxt.js, where I have installed aws-amplify (which automatically installs aws-sdk) in order that I can implement authentication with AWS Cognito.

In both cases, this works very nicely, but the problems come when I build production versions.

In both cases, I end up with massive bundle sizes which (thanks to webpack-bundle-analyzer) I can immediately see are caused by the aws-sdk which appears to contain code to implement every AWS service, under the sun, despite the fact that I am only importing AWS Cognito's: "Auth" (import { Auth } from 'aws-amplify')

I have tried creating a custom AWS SDK for JavaScript, which only includes the service: AWS.CognitoIdentity, but despite incorporating that (presumably incorrectly), I still end up with the same bundle size (and aws-sdk files) when I build the projects.

As I say, this is happening in both Nuxt and Vue project, but in order to simplify this, I for now just want to find the solution to a very basic sample project created with Vue.

I think I must be doing something dumb, but I can't work out what that is.

Any help would be greatly appreciated! :-)

Steps to reproduce:

  1. Create a basic Vue.js project with defaults. Run: vue create vue-aws-sdk-inv

[Note: Steps 2 - 4, are not crucial to reproduce issue, but install webpack-bundle-analyzer which provides useful extra info.]

  1. In the new project, install webpack-bundle-analyzer. Run: npm install --save-dev webpack-bundle-analyzer
  2. Create root file: vue.config.js
  3. Add the following code to vue.config.js:
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
module.exports = {
  configureWebpack: {
    plugins: [new BundleAnalyzerPlugin()]
  }
};
  1. As a benchmark, build the project. Run: npm run build

At this stage, the project will build (with no console warnings) and webpack-bundle-analyzer will launch (in the browser) showing the file: chunk-vendors..js, at the top of the tree, containing a bunch of other .js files, all of acceptable size.

  1. Install AWS Amplify (and by default aws-sdk). Run: npm i aws-amplify
  2. Open src/components/HelloWorld.vue and add the following under the tag: import { Auth } from "aws-amplify";
  3. Build the project. Run: npm run build

At this stage, the project will build WITH console warnings regarding the following files being too large:

File                                 Size               Gzipped

dist/js/chunk-vendors.013ac3f0.js    3055.78 KiB        550.49 KiB
dist/js/app.fa2a21c4.js              4.67 KiB           1.67 KiB
dist/css/app.53019c4c.css            0.33 KiB           0.23 KiB

If installed, webpack-bundle-analyzer should launch (in the browser) showing an inflated: chunk-vendors..js, due to a hefty: aws-sdk.

aws-sdk will include api: .json files and lib: .js files for every AWS service I can think of!

The attempt to rectify:

  1. Navigate to: https://sdk.amazonaws.com/builder/js/
  2. Clear all services.
  3. Select just: AWS.CognitoIdentity
  4. Download "Minified" aws-sdk-.js
  5. Download "Default" aws-sdk-.min.js

[Note: the following are the steps I am guessing I'm getting wrong?...]

  1. In the project, search the node_modules directory for aws-sdk.js and aws-sdk.min.js.

They were found in /node_modules/aws-sdk/dist

  1. Replace both files with the downloaded files (renaming to aws-sdk.js and aws-sdk.min.js respectively.)
  2. Build the project. Run: npm run build

Project will build with same console warnings and same massive aws-sdk, as before, containing all the same .js and .json files for a bunch of services that are not actually imported in the application.

Final pieces of analysis:

  1. Remove aws-sdk.js and aws-sdk.min.js from project's: /node_modules/aws-sdk/dist
  2. Build the project. Run: npm run build

Project is built without even referencing these files.

  1. Rename /node_modules/aws-sdk to /node_modules/TEMP_aws-sdk and attempt to build the project.

Build fails, and this proves (I think) that I was at least trying to add the custom versions, of aws-sdk.js and aws-sdk.min.js, somewhere in the correct directory!

Source Code:

vue.config.js:

const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
  .BundleAnalyzerPlugin;
module.exports = {
  configureWebpack: {
    plugins: [new BundleAnalyzerPlugin()]
  }
};

src/components/HelloWorld.vue:

import { Auth } from "aws-amplify";

As said before, any help would be greatly appreciated! :-)


Solution

  • It looks like import { Auth } from "aws-amplify"; doesn't currently allow for tree shaking according to this issue.

    Reading through several related issues, it appears that:

    import Auth from '@aws-amplify/auth';
    

    is the best you can currently do. I suspect that over time, the AWS team will figure out a way to better separate the internals.

    For readers looking for a way to reduce bundle sizes for the aws-sdk package, see this section of the docs.

    In my case:

    import S3 from 'aws-sdk/clients/s3';
    import AWS from 'aws-sdk/global';
    

    cut the bundle size down by quite a lot. That gets it down to ~57k gz to use S3.


    Also, for anyone using nuxt you can just run nuxt build -a to get the build analyzer.