Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

Consider bundle size #2113

Open
brambow opened this issue Nov 14, 2019 · 4 comments
Open

Consider bundle size #2113

brambow opened this issue Nov 14, 2019 · 4 comments
Labels
vsts Paired with ticket in vsts

Comments

@brambow
Copy link

brambow commented Nov 14, 2019

Feature Request

Consider the total library size.

Problem description

Fluent is significantly larger than comparable options, including it's spiritual predecessor SUIR. (244kb gzipped vs 83 for SUIR). While apps that treeshake can reduce the size, I've noticed it's still pretty large. For example, I've been working on a library that uses Fluent, but only imports 10 of Fluent's components and the gzipped size is still over 100kb.

https://bundlephobia.com/result?p=@stardust-ui/[email protected]
image

Here's an example of what stardust is taking up in my library once treeshaking occurs (using source-map-explorer):

According to this, the 10 stardust components I'm using account for 15% of my overall application size at 230kb (All the application is doing here is displaying a Mapbox map)

image

Proposed solution

I'm not really sure. I know a library that considers so much, like accessibility and theming, and has so many components out of the box might be bigger than something like Rebass. But surely there are some opportunities to reduce size. For example, there's a ton of places where you're importing the full lodash library, only to use one function, like _.get(). In those cases, wouldn't it be better to import the individual lodash es modules?

I think Fluent has a lot to like, but its size concerns me a bit and definitely has me looking at other alternatives.

@pkumarie2011 pkumarie2011 added the vsts Paired with ticket in vsts label Nov 14, 2019
@astegmaier
Copy link

astegmaier commented Feb 5, 2020

I tried to do some debugging and testing to measure the impact of importing and using @fluentui/react, and I found some things that might be helpful.

First, I noticed that if I started with a simple "Hello World" app, and added only:

import { themes, Provider } from "@fluentui/react";

const App = () => (
  <Provider theme={themes.teams}>
    <div>Hello from App2!</div>
  </Provider>
);

The tree-shaked, minified bundle size of my app increased by ~800k (!). When I looked closer at what was happening, I found that if I didn't import the entire themes object, and instead directly imported the teams theme, I could get this down to 753k.

Besides that, I found three main reasons for the large size:

  1. As @brambow mentioned, the project frequently imports external dependencies like lodash with statements like import * as _ from "lodash" instead of more granular imports like import { get } from "lodash", so more of those dependencies gets imported than necessary.
  2. Importing a theme implicitly loads all the svg icons used by that theme, even if they are unused.
  3. Importing any theme implicitly loads the code for most of the components in the library (e.g. Dropdown, Menu, etc.), even if they are unused.

Fixing (1) should be pretty straightforward. Fixing (2) and (3) to allow this code to be "pay-to-play" would require some more thought from someone who understands the internal structure of the library, but it should be doable.

Below are the details of my analysis (which you can see in this excel file).

You can also repro the issue yourself from this repo.

image

@layershifter
Copy link
Member

Thanks for digging this!

1 is not an issue as we use babel-plugin-lodash to handle this:

isDistBundle && 'lodash',

You can check our dist files on CDN, for example: https://cdn.jsdelivr.net/npm/@fluentui/[email protected]/dist/es/components/TextArea/TextArea.js

import _invoke from "lodash/invoke";
import _get from "lodash/get";

@astegmaier
Copy link

astegmaier commented Feb 5, 2020

@layershifter - thanks for taking a look!

You're right that the build imports of lodash in the es6 bundle files look granular, so my guess about what was causing so much lodash code to make it into the final tree-shaked bundle was mistaken.

I think (probably) something is still going wrong, though. Below is an image of all the stuff from lodash that makes it into my final tree-shaked bundle. There's a bunch of files that I don't see referenced anywhere within the project (e.g. _deburrLetter.js, _unicodeWords.js, etc.). I'll do some additional debugging to try and understand why this happening, but I'm all ears if you can think of the reason.

EDIT: After looking closely, it looks like there are actually some things (about half of them) in the lodash package that are not in the final tree-shaked bundle, so I think tree-shaking is probably happening, but there's so much stuff because lodash is used extensively in @fabricui/react. Let me know if that makes sense to you - if yes, this is probably not a low-hanging-fruit way of reducing bundle size.

Lodash all-in was only contributing 38kb to the bundle size, though - even if we can't fix this issue, I think the biggest bundle size wins will come from addressing (2) and (3) above. It looks like #2320 should help with (2) - thanks for pointing me to that!

image

@layershifter
Copy link
Member

For 3, yesterday we discovered multiple issues #2324 and going to fix them #2325.

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

No branches or pull requests

4 participants