Open nandorojo opened 2 years ago
I suspect this might be due to the second one where it is importing all of the RNW.
After upgrading to Reanimated v3, which has lower size since it removes all of Reanimated v1 code, the bundle size of the page already decreased by like 20kb (~25%)!
So it may still be due to importing all of RNW, but it seems like the Reanimated size certainly has an impact. Going to investigate further.
I commented out ScrollView
, Image
and FlatList
:
This dropped the page size to 45kb
(down another 20kb):
So there is certainly something to breaking RNW's tree shaking.
The FlatList
is the greatest culprit: importing that adds 11kb
. It looks like that's the size of the actual FlatList
from react-native-web
(it's huge). I thought this might be from reanimated's layout animations, but importing FlatList
directly resulted in the same bundle size.
Overall, this is good news. If this import size is only due to the components, that's likely easy to optimize. However, I don't think that's the full story...
Here is the size with all components, minus FlatList (53kb
):
Interesting. What's the next step? Create an issue on RNW? 😢
I still want to find where the remaining bloat from reanimated is coming from. As for FlatList, probably best to not use on Web. It doesn't offer any benefits besides code sharing anyway, since it doesn't optimize performance on Web or do any virtualization.
So you suggest to completely get rid of the FlatList components on the web and instead replace it with a ScrollView?
It's your call, but if you want to avoid the 10kb of FlatList on web, you could do that yeah.
This is the bundle size with zero components. So reanimated itself is taking up 47kb
out of the 63kb
total.
However, it also has a massive JS load to the right. What is the difference between size and first load JS?
Adding sideEffects: false
significantly decreased the size too. However, I'm unsure if this is safe or not.
Does reanimated Web have side effects, such as initializing global variables? If so, we should put those all into one file.
sideEffects: false
resulted in 79.3kb first load (with other components commented out)
Without sideEffects: false
, it is 116kb
:
These are relative numbers not absolutes, since I have other code commented out. The actual bundle size is larger.
I only found 2 files that edited the global scope and that were used by Web. I found them by searching global.
in VSCode.
Adding these to sideEffects
in Reanimated's package.json
had the same effect as adding sideEffects: false
– a roughly 38kb decrease in bundle size.
This is very promising.
65kb
side, 168kb
first load
sideEffects
:37kb
size (45% lower), 130kb
first load (23% lower)
No impact. I think it's because they're all getting added as Animated.View
on that object. I'll have to see if there is a way to optimize this type of variable or not...
Removing all components brings it down to 70kb, so we are getting an additional 60kb from adding them to Animated
.
What if we remove the components from Animated
, put them into their own files, and then export them one-by-one as named exports?
The bundle size is now 110kb
first load, down from 130kb
if we put them directly on Animated
. This is using only a View
, meaning it is now successfully tree shaking per-component.
It's worth noting that this is importing
Animated
fromreact-native-reanimated
, but it is not importing any components. As a result, components are tree-shaking when they aren't used.
However, this is now completely acceptable. Notice that the page size is only 17kb – 16kb lower than /
, which has no reanimated components.
Before starting, using Reanimated on a page added 81kb
. Now, it's only 17kb
.
The only missing piece is trying to get backwards compatibility for Animated.View
usage...
Success!
Doing this results in no additional bundle size, meaning it is tree shaking the variables at least. The only missing piece is, can we add Animated.View
to Animated
without importing all components? Can PURE
be used for this?
I think I have the solution for named exports: do both named exports and default one. Now that the default one can be tree shaken, as long as you don't import it, then it won't affect bundle size.
Instead, if we use star imports, it will import a smaller bundle:
import * as Animated from 'react-native-reanimated'
With this method, we can have no breaking changes and still preserve Animated.View
usage for both default imports and star imports.
Default import has been solved. Opening a PR on react-native-reanimated.
Here are the preliminary results for an empty page. Compare
/
to/reanimated
. They are both identical, but Reanimated has80kb
greater.Some questions to answer:
Is this because Reanimated itself is 80 kb? Or, is it because Reanimated is importing all of
react-native-web
, breaking its babel plugin that tree shakes imports fromreact-native
directly?a. If it is indeed breaking because it's importing all of RNW, this is an easy solution. We just need to split the
createAnimatedComponent
calls ofText
,View
, etc. into their own files. See Dripsy for an example.What does adding
sideEffects: true
to Reanimated change?