-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
react-native support #123
Comments
I'd love if bun worked with React Native Regardless of bugs with bun today, support for Hermes is harder Bun doesn't currently transpile to ES6 (or backwards transpilation at all, yet), and Hermes lacks native support for many JavaScript features, like classes It is unlikely Bun will support transpiling classes (for similar reasons as esbuild) Bun uses JavaScriptCore as it's engine, I do think it would be pretty interesting to get bun's JavaScript environment to run as the engine. That would mean adding support for JSI and adding Android + iOS targets & architectures. This won't happen soon, but I think that would be an interesting way to make it work Regarding this particular problem:
It would be tough to use bun as just the transpiler today, and much easier if used as both the bundler & transpiler For that to possibly work, it would probably not be using |
kudos for your work @Jarred-Sumner, it' insane! |
JS Engine React Native used to use JavaScriptCore (which Bun uses), but they wrote Hermes for perf reasons on mobile. It wouldn't make sense to go back to JSC now. And Hermes is recently the default engine for all RN apps. Bundler The Metro bundler though is a PITA and would be great to get rid of, and use Bun instead. There is an alternative Webpack-based bundler for React Native called repack which would be a good starting point. Transpiler As mentioned above, Hermes doesn't support classes yet, and esbuild (used by Bun), doesn't support transpiling to ES5. If Bun could use SWC for its transpiler, then it would be possible. I also wonder if Bun considered Hermes instead of JSC. It's optimized for fast startup times. |
It seems the hermes runtime is too immature to be a target for much other than Facebook's metro with it's specific configuration. It does improve TTI but appears to be slower and less efficient in all other regards. It also currently implements pretty wild unsafe behavior such as treating In my react-native app I've opted out of Hermes in favor of keeping JSC due to runtime performance and stability issues with Hermes. Switching between the two is as simple as a single flag, it's transparent. From what I've gathered alternative runtimes are not going away in react-native. It seems going forward that react-native will be largely runtime agnostic and support any runtime that supports JSI. You can currently switch between JSC, V8, or Hermes more or less seamlessly in a react-native app. V8 on iOS is a bit more complex since it has to be compiled without JIT -- IIRC Apple's rescrictions don't disallow JS engines outside of JSC but rather they disallow any sort of JIT compilation outside of JSC. With that, it would probably be possible and perhaps even easy to drop Bun into react-native as a replacement engine since react-native already runs on and will continue to run on JSC in the future. I don't have the time to try it myself right now but I think Bun definitely has a ton of potential for improving the (generally awful) react-native DX. |
If anybody with more cpp experience than me (I have zero) wants to look into this here is react-native's implementation of a JSC runtime for react-native. https://github.com/facebook/react-native/blob/main/ReactCommon/jsc/JSCRuntime.cpp |
Lately I've decided to give up on React Native and am opting for Tauri mobile instead. Posting it here for others who might be fed up w/ the difficulty of integrating RN with the evolving JS ecosystem. |
I notice that this issue turned pretty quick from supporting metro to using bun as the runtime for react native applications. As a react native developer I'm much more interested in replacing node with bun than I am replacing hermes. |
I'm more interested in the opposite 😄 hermes has numerous severe problems that plague us constantly. Lack of block scoping facebook/hermes#575 (comment), an object property limit that prevents processing source maps facebook/hermes#851, 800-3200x worse date perf facebook/hermes#930, poor proxy perf, among other things. A more stable, feature complete, and performant runtime would be amazing! |
That's a fair take for sure. I just wanted to point out that there are very different usages of bun in a react native project with different levels of difficulty. Even if I could just replace pnpm and jest with bun that would be a huge win for our team if the perf benefits reflect benchmarks. |
@evelant RN runs on JSC already, at least if you turn of hermes, which is the same engine that runs bun. Bun makes sense as a package manager and maybe eventually bundler for RN but not really as the runtime. |
If you are interested in potentially better DX, I've gotten Vite to serve RN and web at the same time. https://twitter.com/natebirdman/status/1698188508329050318 Working on getting it cleaned up for an initial release. |
I would love to see some kind of Hermes kinda implementation in Bun, this will parse & compile the JS / TS code, optimize during the build time. Making start-up faster and reduce memory consumption. Basically the code will be precompiled to bytecode. |
Here are some of my thoughts on adding React Native support to Bun (or any bundler). React Native resolutionA Metro replacement needs to be capable of the following:
Community transpilationMetro transpiles all files using the project Transpiling React NativeOne of the hardest parts of supporting React Native projects, is transpiling the Additionally, the sourcemap format includes a custom The global runtime of React Native is a bit of a mystery, adding global side-effects that run before In my opinion, all of these globals should be split out of the core React Native JS bundle and potentially instantiated natively to prevent the need for all this complexity in the bundling pipeline. As of writing this, these appear to be all the globals (iOS + Hermes) that are instantiated on the global: React Native iOS JS side-effects
React Native iOS native side-effects (Hermes)
Metro globalsMost of these come from the metro runtime React Refresh, and the
So plan accordingly when creating any bundler-runtime code or attempting to simplify the bundling setup. Multi-platform supportOne often overlooked feature of Metro is the simultaneous multi-platform support. In the past, when I've tried to get other bundlers working for React Native this has been one the bigger blockers. As soon as you want to connect different platforms to the same server, you end up having to spin up multiple different bundler instances which bogs everything down. Being able to make all levels of the caching aware of different platforms is critical for keeping things snappy. If bun could allow for providing abstract metadata like This will also be useful for React Server Components, being able to leverage the same graph and just modify transformation/resolution based on an output target. ServingThe dev server needs to support serving Unlike Webpack, Metro is lazy by default which is nice because it means you don't have to worry about multiple platforms bundling on start-up. Metro used to have a bunch of middleware required for debugging, but the Expo team has removed a bunch of this in Expo SDK 49 so debugging shouldn't need to be tied to the bundler implementation. AssetsAssets are matched against a glob of extensions and registered using React Native, images are measured during bundling. All assets support multi-resolution asset extensions, e.g. Worth noting that JSON can be treated as both an asset and a source file. Expo RouterTo support the basics of Expo Router, we'd need the ability to import directories, e.g. FreebiesThere's currently no bundle splitting or tree-shaking in Metro (and no official plans to support it) so there's no caveats there to account for. We'll eventually build multi-bundle support into the Expo OTA service, but in the meantime, you'll need a system for outputting a single chunk on native. Async chunk loading in Metro is pretty straightforward simply provide a global that can fetch and evaluate a bundle. One nice feature is that the dependency map (representing import ID to global module ID) is provided to the module, and configurable in the serializer. This means you don't need to have some external DLL manifest to map remote chunk URIs to module IDs. A good (but outdated) reference is this branch which gets the basics working with ESBuild. This list isn't exhaustive, but I hope it helps shed some light on the issues. |
@EvanBacon great write up. For the vite react native implementation I have I just made a prebuilt react native package that gets aliased, you could build out a bunch of them for each version of react and it’s only a small js script to combine esbuild and remove flow types. Was a lot easier than trying to integrate flow into bundler everywhere. |
@natew one issue with rolling up
The Android equivalent (uniques only):
So the fork would need to have a fair amount of entry files left in place. |
Yea, had to do a custom transform where it exposes all the internal paths and forces all their exports to not be shaken out by rollup, now that I think about it that part does have a bit of complexity beyond just esbuild and flow. |
I'd love to see this, but doesn't Bun require JIT support which isn't available on iOS? |
I always thought jsc was the exception to that rule (well, who knows after eu gatekeeper stuff), so in theory bun is fine? But I've also heard it's only out of process jsc that is okay so maybe not viable. |
Unfortunately not. iOS will only allow JIT in a WKWebView that runs in another process so you can take advantage a little bit for hybrid apps. No way to access JSC in that process and there is some latency from interprocess communication through the provided SDK. I like WKWebView for document editing since content editable is superior these days to the buggy TextKit 2. It is nice to have that accelerated with JIT. ProseMirror and CodeMirror are very nice on iOS. It wouldn't work in general for React Native though. No JIT or WASM in JSC. These days most React native is more about AoT bytecode generation for faster startup times. Even on Android where JIT is allowed, React Native just interprets. |
Interestingly, this all worked for me:
This ran the app in the simulator with Metro running in the background. |
But is there any benefit of running these commands via bun as opposed to any other package manager like yarn or npm ? |
Note that the iOS simulator supports JIT in JSC, but the actual iOS device does not. |
@EvanBacon My app is NOTE : this is not expo |
Any updates on this ? |
Hi
I know this project is in alpha and we are at the start of the road. Right now I tried to make bun work with react-native (Hermes) but I got the following error. Hope to have react-native support in the future and consider it.
The text was updated successfully, but these errors were encountered: