Description
What happened?
Due to certain esbuild optimizations, Hermes generates more bytecode compared to the standard Metro bundle.
It hepens for me with the folowing case:
I use styled-components
and react-native-gesture-handler
and found that then more I have react-native-gesture-handler
components wrapped into styled
the more my hermes output bundle.
It seems the problem not in the styled-components
and react-native-gesture-handler
themself but more esbuild
and hermes
.
The problem can be boiled down to the following code:
// TouchableOpacity.tsx
let Reanimated;
try {
Reanimated = require('react-native-reanimated');
} catch (e) {
Reanimated = undefined;
}
export const TouchableOpacity = ({ children }) => {
Reanimated.useSharedValue(0);
return children;
};
// index.tsx
const { TouchableOpacity } from './TouchableOpacity'
const styled = (Component: React.ComponentType) => (styles: any) => {
return (props: any) => <Component {...props} style={styles} />;
};
// input
const Comp = styled(View)``;
// output
// var _a;
// const Comp = styled(View)(_a || (_a = null));
It seems that the combination of _a || (_a = null)
and (this part in the react-native-gesture-handler
lib ) are contributing to the large bundle size.
Affected Package
@rnx-kit/metro-serializer-esbuild
Version
0.2.0
Which platforms are you seeing this issue on?
- Android
- iOS
- macOS
- Windows
System Information
System:
OS: macOS 14.5
CPU: (10) arm64 Apple M1 Pro
Memory: 1.89 GB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 22.7.0
path: ~/.asdf/installs/nodejs/22.7.0/bin/node
Yarn:
version: 3.6.4
path: /opt/homebrew/bin/yarn
npm:
version: 10.8.2
path: ~/.asdf/plugins/nodejs/shims/npm
Watchman: Not Found
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.5
- iOS 17.5
- macOS 14.5
- tvOS 17.5
- visionOS 1.2
- watchOS 10.5
Android SDK:
API Levels:
- "30"
- "31"
- "32"
- "33"
- "34"
Build Tools:
- 30.0.2
- 30.0.3
- 31.0.0
- 33.0.0
- 33.0.1
- 33.0.2
- 34.0.0
System Images:
- android-23 | Google APIs ARM 64 v8a
- android-29 | Google APIs ARM 64 v8a
- android-30 | Google APIs ARM 64 v8a
- android-31 | ARM 64 v8a
- android-31 | Google APIs ARM 64 v8a
- android-31 | Google Play ARM 64 v8a
- android-32 | Google APIs ARM 64 v8a
- android-33 | Google APIs ARM 64 v8a
Android NDK: Not Found
IDEs:
Android Studio: 2024.1 AI-241.18034.62.2411.12169540
Xcode:
version: 15.4/15F31d
path: /usr/bin/xcodebuild
Languages:
Java:
version: 17.0.10
Ruby:
version: 3.0.3
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.3.1
wanted: 18.3.1
react-native:
installed: 0.75.3
wanted: 0.75.3
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: Not found
newArchEnabled: false
Steps to Reproduce
- Clone https://github.com/Augustach/esbuild-hermes-issue
- Run the script
yarn copy-modules
. This will generate 1000 copies of the./src/template.tsx
file. - Run
ESBUILD=true yarn build
to create the esbuild bundle. - Check the size of the
./output/index.android.bundle.hrs
Hermes bundle. - Run
ESBUILD=true yarn build
to create the metro bundle. - Check the size of the
./output/index.android.bundle.hrs
Hermes bundle.
Expected Result (ER): The size of the esbuild bundle should be less than or equal to the size of the Metro bundle.
Actual Result (AR): The size of the esbuild bundle (~2.7MB) is much larger than the bundle (~1.3MB) produced by Metro.
Code of Conduct
- I agree to follow this project's Code of Conduct