4 votes

React Native Skia - high performance C++ user interfaces with React

3 comments

  1. [3]
    Greg
    Link
    tl;dr Shopify ported Flutter's rendering model to React! I wasn't sure if something like this existed, but I went off looking for it after this thread got me thinking about the idea (thanks...

    tl;dr Shopify ported Flutter's rendering model to React!


    I wasn't sure if something like this existed, but I went off looking for it after this thread got me thinking about the idea (thanks @skybrian!) and I'm pleased to see that it does.

    The basic premise is this: React provides a really good model for building user interfaces, but was originally created to output HTML/CSS and rely on a browser to render it. React Native built on this significantly, moving the layout calculations to yoga and outputting native iOS or Android UI elements instead of HTML - this was huge for mobile development, but it doesn't cover every use case, and perhaps most importantly doesn't cover desktop applications (Microsoft does maintain Windows and macOS forks, but with the drawbacks of using a heavily modified version of the codebase rather than an additional library). All of this has led to Electron apps taking over the world, which bundle Chromium into the desktop app so they can stick with HTML & CSS to render the UI and bring a pretty heavy overhead in the process.

    Google's Flutter takes a similar approach to React in terms of development style, but uses Skia to build the UI at a much lower level by drawing primitives directly to the screen on whatever platform you happen to be running on, desktop included. There are pros and cons to this as a technical approach, but the biggest issue with actually using Flutter is simply that the React ecosystem (libraries, experienced developers, support forums, etc.) is orders of magnitude larger.

    Putting that all together, what Shopify have done here is brilliant: it lays the groundwork to combine Electron's ease of development and Flutter's performance in a single codebase that still uses the standard, off-the-shelf React that everyone already knows.

    3 votes
    1. [2]
      skybrian
      Link Parent
      It seems like an interesting technology for people who are interested in Flutter but not in switching to Dart. But I'm somewhat skeptical that third-party React-based libraries would just work...

      It seems like an interesting technology for people who are interested in Flutter but not in switching to Dart.

      But I'm somewhat skeptical that third-party React-based libraries would just work with it. Seems like they'd need some adjustments?

      1 vote
      1. Greg
        (edited )
        Link Parent
        There are a few big parts of the puzzle still missing before anyone can actually bundle this up into a viable replacement for Electron, but this proves that it's possible and brings us maybe...

        There are a few big parts of the puzzle still missing before anyone can actually bundle this up into a viable replacement for Electron, but this proves that it's possible and brings us maybe 75-85% of the way there, which is why I'm excited!

        [Edit: Sorry, this is a much longer reply than I intended… I’ve kind of ended up thinking out loud about the potential design here and it got away from me a bit]

        Right now, you should get drop in compatibility with third party libraries for things like state management, navigation, testing, I/O, that kind of stuff, as well as being able to retain & share all the client side business logic from whatever existing React/RN apps you might have. That's no small advantage, but yeah, I'm excluding anything that the user can actually see on screen from that list, which is a pretty big caveat for a UI tool.

        To get drop in UI compatibility with all existing JS-only React Native libraries, someone will need to implement the RN core UI components in terms of Skia primitives. It'll be a bit of a slog to actually do that, but there are only ten of them to build, and once it's done it unlocks whole chains of existing UI elements (again, both third party libraries and existing code within companies and organisations) that depend only on the core components and each other. I found at least one example of some pretty cool Skia UI elements out there already - do the same but following the existing RN APIs for things like Button or ScrollView and we're in business.

        For using Skia on Android, iOS, or macOS that should theoretically be it - those platforms already have support for the existing native code and bindings in both React Native itself and the libraries built for it, so once the expected building blocks are there for the UI the libraries shouldn't even be aware of the difference.

        Unfortunately Windows is a bit trickier, and obviously that's by far the most important for desktop apps. If we want to stick with vanilla React Native rather than the Microsoft fork, a lot of the native code that drives the developer-facing JS APIs simply won't work, nor will any native modules or dependencies in existing libraries. This is a fundamentally harder problem than just reimplementing the default Button component in terms of paths or polygons will be.

        With any luck, the Windows Subsystem for Android might cover enough ground to compile and run the existing Android React Native code, and if that works it brings the vast majority of libraries into scope without modification as well.

        Worst case, if that turns out not to be viable for any reason (particularly performance/bloat, which is exactly what this whole idea is attempting to get away from!), we'd need to modify the native code and/or build process to output Windows-compatible calls directly.

        That's verging very close to what the Windows fork already is, although a system agnostic renderer would still bring a few advantages in terms of cross platform design and build. It may even be that without needing to worry about rendering and components (as the current Windows build does), the changes for Windows compilation would be minimal enough to maintain as part of React Native itself. That'd also mean that libraries with native code would need at least some modification to work, but given the other options of not using them at all (via Electron) or rewriting them entirely from scratch (via Flutter), the extra 10-15% development overhead might not seem so bad. My intuition is that even this worst case would be a pretty solid improvement on the status quo.

        [Edit 2] Come to think of it, using the CanvasKit Skia renderer with a standalone Canvas implementation could also be potentially interesting as a direct replacement for Electron. It’s kind of absurd to go from C++ to WebAssembly to WebGL to whatever your Canvas of choice is implemented in rather than just rendering directly, but it’s still a lot better than doing all that and having to bring a whole browser and HTML DOM along for the ride as Electron does.

        2 votes