-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
In some cases, the Hermes bundler produces a larger bundle with Esbuild than with Metro. #3361
Comments
Thanks for reporting this, @Augustach! I think this comes down to esbuild enabling lowering of template literals because Hermes only partially supports it (depending on the version, it might be call site caching or Can you try adding |
@tido64 thanks for the quick response! Confirm that adding But the problem is not primarily related to styled-components and tagged templates. It’s due to some combination of how esbuild and Hermes generate the code. Here is an example with enum that gets transpiled into a combination like the one below, which produces the same problem as tagged templates:: var _TextType;
_TextType = _TextType || (_TextType = {}) You can check it here: |
Thanks for verifying the change. I've merged it since I don't think it relates to the new issue you brought up and it's good to have regardless. I had a quick look at the enum case, and I can't say I can repro your output. This is what I see for Metro: var TextType = /*#__PURE__*/function (TextType) {
TextType[TextType["Simple"] = 1] = "Simple";
return TextType;
}(TextType || {});
var Comp1 = function Comp1(_ref) {
var text = _ref.text;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
children: text
});
};
var Comp2 = function Comp2(_ref2) {
var text = _ref2.text;
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
children: text
});
};
var Module0 = exports.Module0 = function Module0() {
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_$$_REQUIRE(_dependencyMap[4], "../../TouchableOpacity").TouchableOpacity, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Comp1, {
text: TextType.Simple
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp2, {
text: TextType.Simple
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp3, {
text: TextType.Simple
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp4, {
text: TextType.Simple
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(Comp5, {
text: TextType.Simple
})]
});
}; vs. the equivalent after going through esbuild: var TextType = /* @__PURE__ */ function(TextType1001) {
TextType1001[TextType1001["Simple"] = 1] = "Simple";
return TextType1001;
}(TextType || {});
var Comp1 = function Comp12(_ref2) {
var text = _ref2.text;
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native2.Text, {
children: text
});
};
var Comp2 = function Comp22(_ref2) {
var text = _ref2.text;
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_react_native2.Text, {
children: text
});
};
var import_jsx_runtime22 = __toESM(require_jsx_runtime());
var Module0 = function Module02() {
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(TouchableOpacity3, {
children: [/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp1, {
text: TextType.Simple
}), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp2, {
text: TextType.Simple
}), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp3, {
text: TextType.Simple
}), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp4, {
text: TextType.Simple
}), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Comp5, {
text: TextType.Simple
})]
});
};
|
Actually, I do know where some of this comes from. There is an overhead of injecting a function call into every module to ensure polyfills etc. are run before the main module: rnx-kit/packages/metro-serializer-esbuild/src/index.ts Lines 263 to 274 in 20f6de0
Removing it shaves off ~100KB of the bundle (though the final bundle won't load properly). This is a technical limitation of the esbuild API not allowing arbitrary code to be inject at the global level (the equivalent to Metro's Edit: There's an open issue on this: evanw/esbuild#1557 |
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
andreact-native-gesture-handler
and found that then more I havereact-native-gesture-handler
components wrapped intostyled
the more my hermes output bundle.It seems the problem not in the
styled-components
andreact-native-gesture-handler
themself but moreesbuild
andhermes
.The problem can be boiled down to the following code:
It seems that the combination of
_a || (_a = null)
and (this part in thereact-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?
System Information
Steps to Reproduce
yarn copy-modules
. This will generate 1000 copies of the./src/template.tsx
file.ESBUILD=true yarn build
to create the esbuild bundle../output/index.android.bundle.hrs
Hermes bundle.ESBUILD=true yarn build
to create the metro bundle../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
The text was updated successfully, but these errors were encountered: