Open luzat opened 1 week ago
Thanks for the info. We're also investigating this issue as well.
@luzat can you also share what tool you used and how you recorded the size?
@wingkwong I set up a basic Remix v2 project with Vite and mostly default settings. I manually added NextUI according to the documentation with single components (only Button
and its animation dependencies). I added a single button to the _index
route.
I checked the bundles that were generated with NODE_ENV=production npx vite-bundle-visualizer
. The _index
route included 212 KB from framer-motion
. After patching the ripple effect to dynamically import domAnimation
the _index
route shrank by 150 KB and a separate chunk of that size, which contained a large part of framer-motion
, was created instead. The _index
route still dynamically loaded that chunk, but did not need that code for the initial render.
I did not test with disabled animations, but in that case the import should have been skipped, given that the animation is included conditionally, and 45 to 150 KB saved.
I seem to be getting this error: Warning: React does not recognize the disableAnimation
prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase disableanimation
instead. If you
accidentally passed it from a parent component, remove it from the DOM element. The reason is caused by the Avatar component
Is your feature request related to a problem? Please describe.
Just adding a NextUI button increases bundle size a lot.
framer-motion
contributes 212 KB (uncompressed) in a production build here. It would be nice if a that could be reduced or loaded asynchronously.A second problem is, that Framer Motion is also be loaded if animations are disabled with
disableAnimation={true}
.Describe the solution you'd like
According to the framer Motion guide it's possible to load features asynchronously using a dynamic import. For many use cases quick initial loading would be preferable over having animations loaded right away.
2929 already did most of the work required from what I can tell. In a test, I did replace the
domAnimation
in theripple
effect by a dynamic port and Vite did split the 212 KBframer-motion
chunk into 59 KB to be loaded initially and a large 150 KB (or 45 KB with Brotli) chunk that can be loaded asynchronously. I feel that this is a huge amount. Also, if the dynamic import is never invoked whendisableAnimation={true}
, this code would never have to be downloaded.I do not know if any other components would not work with that pattern or if there are cases when you might want to load the features synchronously. There could be at least two ways to go about this:
domAnimation
as a dynamic/static import and pass that to NextUI?)await import('@nextui/dom-animation')
or similarEven if code splitting won't work in all cases/components, this might be a helpful optimization for some projects.
Describe alternatives you've considered
Screenshots or Videos
No response