zooniverse / front-end-monorepo

A rebuild of the front-end for zooniverse.org
https://www.zooniverse.org
Apache License 2.0
104 stars 30 forks source link

lib-react-components is over 700k of JavaScript #2534

Open eatyourgreens opened 2 years ago

eatyourgreens commented 2 years ago

Package

lib-react-components

Is your feature request related to a problem? Please describe.

lib-react-components has ~300k of source code (including tests and stories), so maybe ~ 100k of source code for the view components themselves. Webpack builds the library as a single JS file that's around ~700k in size.

You can see this in the webpack build, which warns about about size.

WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the
recommended limit (244 KiB). This can impact web performance.
  Entrypoints:
    main (737 KiB)
       main.js

Describe the solution you'd like

Code splitting into individual js files, for each component, rather than one massive output file, might improve performance.

We can analyse the output file with webpack tools, and see if there's anything that can be trimmed or lazy-loaded.

Additional context

Tree shaking and code splitting in Webpack is a good read about minimising the size of exported code.

eatyourgreens commented 1 year ago

Here's a quick screenshot from webpack bundle analyzer. Font Awesome is more than 1MB, with i18next the second largest contributor to the bundle (it's ~100k.)

Screenshot from webpack-bundle-analyzer showing that Font Awesome more than doubles the size of the output bundle.
eatyourgreens commented 1 year ago

The whole of lodash is also being included, even though we only use a handful of lodash helpers.

Screenshot of the bundle analyser output, showing that lodash is a big contributor to final bundle size.
goplayoutside3 commented 1 year ago

Re: the Slack thread discussion about this package - My understanding is that lib-react-components’ primary purpose is to be used in FEM. It’s published as an npm package, but do other zoo-repos actually use it? I ask because I think it’s important to measure how much time could and should be dedicated to reducing the size of lib-react-components when its largest dependencies are already going to be used in its FEM parent packages (React & i18next in lib-classifier or app-project).

eatyourgreens commented 1 year ago

Zoo Notes uses it. I think Mapping Viz might use it too. Perhaps also Alice? Any new project since about 2018 probably uses it.

In terms of FEM, @zooniverse/react-components is the biggest contributor to bundle size in the NextJS apps, leading to even static pages like the Team page having a weight of > 1MB.

eatyourgreens commented 1 year ago

React is side-loaded as a peer dependency, so isn't included in the output bundle. We could make i18next a peer dependency too.

eatyourgreens commented 1 year ago

In terms of localisation, ~100k of the bundle size comes from bundling all the language strings into main.js. Can we change that so that language strings are loaded at run time? If we could, that should make the library a lot faster.

goplayoutside3 commented 1 year ago

Zoo Notes uses it. I think Mapping Viz might use it too. Perhaps also Alice? Any new project since about 2018 probably uses it.

You're right! mapping-viz-tools uses it.

Can we change that so that language strings are loaded at run time? If we could, that should make the library a lot faster.

I'm not sure how to do so off the top of my head, but I think it's a good idea!

eatyourgreens commented 1 year ago

By the way, I published v1.2.0 a couple of weeks ago. It turns out we hadn't published a new version in about a year. I'd guess Mapping Viz is probably still on 1.1.0.

eatyourgreens commented 1 year ago

It turns out that declaring i18next and react-i18next as external dependencies also reduces the output size, so I'm going to push that change to #3761. One result of that change is that consuming apps are assumed to supply those libraries, so that would be a breaking change for Zoo Notes and Mapping Viz. In the monorepo, the classifier and react-components will load react-i18next from the NextJS apps.

We already require consuming apps to use React and Grommet, so requiring them to use react-i18next seems reasonable to me.

eatyourgreens commented 1 year ago

Media loads in ~150k of mime-types just to check whether a URL is a video, audio or image file. That can be optimised, probably by building our own list of supported file extensions.

https://github.com/zooniverse/front-end-monorepo/blob/c21b61d0888e3a4943f409754c74d017a8c1bc33/packages/lib-react-components/src/Media/Media.js#L9

That's used in Markdownz (maybe in other components?). It wouldn't surprise me if Markdownz and Media make up most of the ~700k build size.

eatyourgreens commented 1 year ago

If I remove Media and Markdownz from the build, the output bundle size drops to ~350k!

eatyourgreens commented 9 months ago

@goplayoutside3 Since version 1.11, the package size has almost doubled, to 1.2MB.

https://bundlephobia.com/package/@zooniverse/react-components@1.11.0

Screenshot of the library size as reported by Bundlephobia. The minified package size has jumped from about 600k to 1.2MB.

eatyourgreens commented 9 months ago

I think the big jump in size was the addition of markdownz in v1.8.

https://bundlephobia.com/package/@zooniverse/react-components@1.8.1

https://bundlephobia.com/package/@zooniverse/react-components@1.7.0

goplayoutside3 commented 8 months ago

True! AuthModal and several hooks have also been added recently

eatyourgreens commented 8 months ago

Most of the size increase is coming from rehype, which is ~240k. I've opened https://github.com/zooniverse/markdownz/pull/242 to use rehype in Node, but rehype-dom in browsers. That should knock ~200k off the browser bundle size.

markdownz jumped from ~370k to ~625k when I added Rehype.

markdownz also uses mime-db, which says this in its Readme:

If you're crazy enough to use this in the browser…

eatyourgreens commented 8 months ago

I've opened https://github.com/zooniverse/markdownz/pull/245 to remove markdown-it-html5-embed and mime-db in the browser bundle. markdown-it-html5-embed was triggering dependabot security warnings, so it would be good to remove it anyway.

goplayoutside3 commented 8 months ago

Awesome thanks!