Closed jamonholmgren closed 2 years ago
Thank you for filing this @jamonholmgren! I will explain what is going on, and then defer to @tido64 to decide what we can do about it.
We use esbuild to make tree shaking work with Metro.
We configure esbuild to target an "es5" runtime environment to ensure that we're compatible with Hermes. Hermes doesn't fully support es6 yet.
Esbuild doesn't fully support transpiling down to "es5", though. See here:
If you use a syntax feature that esbuild doesn't yet have support for transforming to your current language target, esbuild will generate an error where the unsupported syntax is used. This is often the case when targeting the es5 language version, for example, since esbuild only supports transforming most newer JavaScript syntax features to es6.
So this puts you in a bind. Effectively, you have to write your code in es5 for our tree shaking solution to work as it stands today.
I tried changing the esbuild target to es6 (by hand, in node_modules) and it works just fine. es6 bundle is made. Ignite sample app loads it just fine (after a bit of hacking to make debug builds load from a file).
This is where @tido64 comes in.
Should we expose a "target" option in the tree shaking config? e.g. "hermes" (implies es5), "es6", and maybe "esnext"?
Whatever is decided, we need to update the README and the guides which cover tree shaking to explain this limitation, what it looks like when you run into it, and how to work around it (or if you have to bail on the whole thing).
Attached picture of what esbuild emits when it runs into code it can't transform to es5 (for the docs).
Thank you @afoxman!
I unfortunately do care about Hermes, as we are intending to turn it on by default in future Ignite releases.
Follow-up question: is the Hermes incompatibility with ES6 just some random edge cases, or is it a blocker? Studying the linked issue(s), it's hard to tell.
Secondly: could we transpile from esnext to ES5 after running esbuild, using Babel? So Babel would re-transpile the esbuild output to ES5, and that could be configurable if Hermes is enabled.
For (1), @tido64 will know.
For (2), I don't know how well it would work to transpile the whole bundle after-the-fact. Why not do it earlier, during the Metro run, via a babel plugin? I was able to get something working using this:
presets: [
+ ["@babel/preset-env", { loose: true }],
["@rnx-kit/babel-preset-metro-react-native", { unstable_transformProfile: "esbuild" }],
],
You will need to pass --reset-cache
to Metro the first time you run this.
I am a Babel Novice, so while this no longer makes esbuild/tree shaking upset, it may be doing horrible things to the bundle. But it demonstrates the approach, and from here, I'd consult a Babel Sage for more advice.
I did test it with the Ignite sample app, and things worked.
As Adam mentioned, Hermes only implements selected ES6 features and lacks basic things like blocked-scope variables. If you want more details, I suggest you reach out to the Hermes folks on Discord.
As for providing target
as a parameter, the plugin does support it and I thought I had documented it 😛 You can pass target
as below:
module.exports = makeMetroConfig({
projectRoot: __dirname,
serializer: {
+ customSerializer: MetroSerializer([], { target: "es5" }),
},
transformer: esbuildTransformerConfig,
});
As of esbuild 0.14.49, you can also do:
module.exports = makeMetroConfig({
projectRoot: __dirname,
serializer: {
+ customSerializer: MetroSerializer([], { target: "hermes0.70.0" }),
},
transformer: esbuildTransformerConfig,
});
I haven't tested with hermes0.70.0
a lot so let us know how it works for you.
Submitted a PR to document options.
Also, I wouldn't use @babel/preset-env
as it includes a lot more than you need. For generators, you should include @babel/plugin-transform-regenerator
instead.
Created a WIP PR to track over on Ignite (https://github.com/infinitered/ignite/pull/1984). ~This will be part of our Ignite Maverick release, if we can get it to work reliably.~ Update 2022-08-10: I'm going to punt this to a future release, but still keep the WIP open.
Created a WIP PR to track over on Ignite (infinitered/ignite#1984). This will be part of our Ignite Maverick release, if we can get it to work reliably.
That's awesome! Keep us posted.
These are my thoughts about this topic:
treeShake: true
and we try to customize the MetroSerializer build options:Clone the repo urban-enigma
treeShake: true
target: "es6"
in the MetroSerializer build options with metro-serializer-esbuild
configured in metro.config.js
Transforming generator functions to the configured target environment ("hermes0.7.0") is not supported yet
target: "es6"
is ignored due the following lines:
https://github.com/microsoft/rnx-kit/blob/95f540703b937054bc4c208941c3643907850551/packages/cli/src/metro-config.ts#L149-L165treeShake: false
target: "es6"
in the MetroSerializer build options with metro-serializer-esbuild
configured in metro.config.js
esbuild
bundler will be skipped and metro will do the serializer jobAs far as I know, it's due to this line in metro-react-native-babel-preset
: https://github.com/facebook/metro/blob/cd8548a582f39b66c3683d21eeb4484d864fb018/packages/metro-react-native-babel-preset/src/configs/main.js#L164
regenerator
is disabled when Hermes is enabled. This is why I suggested adding @babel/plugin-transform-regenerator
earlier.
As far as I know, it's due to this line in
metro-react-native-babel-preset
: https://github.com/facebook/metro/blob/cd8548a582f39b66c3683d21eeb4484d864fb018/packages/metro-react-native-babel-preset/src/configs/main.js#L164
regenerator
is disabled when Hermes is enabled. This is why I suggested adding@babel/plugin-transform-regenerator
earlier.
@tido64 the metro-react-native-babel-preset
is not the issue here. The problem is that esbuild
consider the following features as no soported in the target hermes0.7.0
:
@rnx-kit/metro-serializer-esbuild
to 0.1.10
+ supported: {
+ generator: true,
+ }
info esbuild bundle size: 1323827
info Writing bundle output to:, ios/main.jsbundle
info Done writing bundle output
info Copying 18 asset files
info Done copying assets
Done in 10.66s.
🙏 hope that this help!
@ecreeth Thanks for the help. I was merely referring to why there is a diff when targeting Hermes, but I guess I left out the context 😆 In any case, I've submitted a PR to re-enable the features that are safe to include. I looked through the others that are partially implemented and I have decided not to enable them to avoid surprises.
What happened?
I'm currently trying out
@rnx-kit/metro-serializer-esbuild
on Ignite and running into the following error:Current diff: https://github.com/infinitered/ignite/compare/rnx-kit-esbuild
I can't figure out where the target is configured for esbuild so I can change it to
esnext
or similar. Ideas?Affected Package
@rnx-kit/metro-serializer-esbuild
Version
0.1.9
Which platforms are you seeing this issue on?
System Information