software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.87k stars 1.3k forks source link

`react-native-reanimated/plugin` babel plugin increases the size by 3x #5954

Closed SYoder1 closed 2 weeks ago

SYoder1 commented 5 months ago

Description

I am using react-native-web and looking into tree shaking to identify some size issues with our bundle. Everything with reanimated is working correctly, but using a bundle inspector I see that the uncompress package of reanimated is ~800KB. This is the largest package we have and the total bundle size is around 4MB.

I found out that if you disable the react-native-reanimated/plugin babel plugin the size drops to ~230KB.

I see in the docs that the plugin is not required, but would require manual steps of adding in dependency arrays to a few hooks. I tried to make these changes, but there were a few other dependencies that started to error out then.

Is this expected to increase the bundle size by that much?

With the plugin enabled:

Screenshot 2024-04-29 at 11 59 35 AM

With the plugin disabled:

Screenshot 2024-04-29 at 12 01 14 PM

Other Versions: Webpack: 5.91.0 @babel/core: 7.20.0 react-native-web: 0.19.10

Steps to reproduce

In the example project after installing:

  1. Run yarn web:profile
    • This will open a local webpage showing the bundle contents. Do not close out of the webpage, but just kill the server in the terminal.
  2. Comment out the plugin in the babel.config.js file
  3. Re-run yarn web:profile
  4. Compare the 2 reanimated sizes

Snack or a link to a repository

https://github.com/SYoder1/React-Native-Web-Reanimated-Test

Reanimated version

5.6.1

React Native version

0.73.0

Platforms

Android, iOS, Web

JavaScript runtime

None

Workflow

React Native

Architecture

None

Build type

None

Device

None

Device model

No response

Acknowledgements

Yes

tomekzaw commented 5 months ago

Hi @SYoder1, thanks for opening this issue.

Is this expected to increase the bundle size by that much?

The plugin needs to stringify all functions marked as 'worklet;' so they can be copied to a secondary runtime so that might be a reason of the bundle size increase. However, there's no secondary runtime on web so we might want to skip that step (to save up on bundle size) and only auto-generate dependency arrays.

@tjzel What do you think?

tjzel commented 4 months ago

Hi @SYoder1.

We don't have a reliable way of detecting whether the target of the bundle is going to be a native or web platform (correct me here if I'm wrong @bartlomiejbloniarz), therefore to omit the data that's unnecessary on web we have an option that you should pass to the plugin, namely omitNativeOnlyData.

You can read more about it in our docs.

Please let me know if enabling this option fixes the bundle inflation.

SYoder1 commented 4 months ago

Hey @tjzel, I tried it out and saw small improvements with omitNativeOnlyData, I also tried it with substituteWebPlatformChecks and didn't see any changes

While still scratching my head at it, I noticed that the project compiles reanimated in the webpack config. I can't find any place in the docs that say to do this, so do you know if its needed at all? It actually makes the biggest difference around 50%.

const babelLoaderConfiguration = {
  test: /\.js$|jsx?$/,
  // Add every directory that needs to be compiled by Babel during the build.
  include: [
    path.resolve(__dirname, 'index.web.js'), // Entry to your application
    path.resolve(__dirname, 'App.jsx'), // Change this to your main App file
    path.resolve(appDirectory, 'node_modules/react-native-reanimated'),
  ],
  use: {
    loader: 'babel-loader',
    options: {
      cacheDirectory: true,
      presets,
      plugins: ['react-native-web'],
    },
  },
};
tjzel commented 4 months ago

Honestly I'm not that proficient with Webpack. I also don't exactly understand what do you mean by "project compiling Reanimated in the webpack config". Could you elaborate a little more on this?

Anyway, I think it should work without this setting, we never had something like this in our Webpack configs when we used them.

SYoder1 commented 4 months ago

I am not an expert in webpack either, and there was a comment in the code for a long time ago "// Add every directory that needs to be compiled by Babel during the build." and reanimated was part of it.

I think what was happening was we were recompiling reanimated from typescript to a esmodule at build time, instead of using the module that is part of the package.

szydlovsky commented 3 months ago

Hi again @SYoder1, is the issue still relevant with the mentioned "fixes" or is there still something you would like us to look at? 😄

markymc commented 2 weeks ago

@SYoder1 ping on this as I'm interested to learn if I can reduce my bundle size too. :)

SYoder1 commented 2 weeks ago

The size is much better now after I updated my webpack to not transform the package. I also added to my webpack config to cut down on the size too.

[
        'react-native-web',
        [
          'react-native-reanimated/plugin',
          {
            // Web only reanimated config
            omitNativeOnlyData: true,
            substituteWebPlatformChecks: true,
          },
        ],
      ],