Proton Native is a way to make cross-platform desktop apps with React, without using Electron or any sort of web browser. Your React code gets translated into Qt or wxWidgets API calls and runs directly on the machine.
After a long time, Proton Native V1 was starting to show it's age. So I ended up making a complete rewrite that includes a lot of the most requested features including flexbox, styling, hot reloading, and components with the same API as React Native.
For those of you who value native components, I've also been working on an experimental wxWidgets backend. There are only a few components, but I hope to implement all the components of the Qt backend soon.
Hello, as a long time proton-native follower, I was thrilled to see ~40 issues closed today for v2 when I woke up in the morning :-)
Congratulations for the v2 release!! I still couldn’t try out right away as I’m on macOS + node v13... but I’ll gonna install nvm as fast as I can :-) Thanks for your great work, it’s super useful for everybody.
I’m still kinda sad about the fate of libui— it was a great project to implement UIs, but Qt was a reasonable point, I think. I’m very looking forwards to the wxWidgets backend...for the true native widgets and the benefit it provides.
Thanks again for your great work on proton-native!!
This is incredible! Last semester I had my undergraduate software engineering class make Electron apps as group projects but I've been looking for alternatives. I'll try this out and let you know how it goes!
> ...requested features including flexbox, styling, hot reloading, and components with the same API as React Native.
That sounds like the way to go for a near 1:1 port of a cross-platform desktop app for React-based apps. Also the move from libui to Qt for the UI backend sounds interesting for this project to be used as a lightweight alternative to Electron.
To be a true alternative to Electron one must provide a simple migration path for existing Electron apps to Proton Native which would change everything in cross-platform desktop app development.
> To be a true alternative to Electron one must provide a simple migration path for existing Electron apps to Proton Native which would change everything in cross-platform desktop app development.
That only makes it an increasingly attractive alternative for those who already have an app built on Electron, and has little to do with whether Proton is a “true alternative”. If it can viably permit developing an app without Electron, it’s a true alternative. How easy it is to migrate an app from Electron is a separate matter.
The library is already built to be largely library agnostic. To add a new library, just add a file that translates my calls to the library calls. This is how I achieved both Qt and wxWidgets backends.
First off, well done, this looks like a good initiative and you've clearly worked hard on it!
My main question is about app size. Once one has fully built an app and is ready to distribute it to users... how does the file size compare to an Electron app?
The only thing that meaningfully contributes to the size of the app is the size of the GUI library libraries. It currently bundles both Mac and Windows, so you can build packages for each and remove the libraries you don't need. It should be around 50 MB maximum.
> But those components are not native, meaning they are drawn by Qt instead of using the components provided by the OS.
In the case of macOS, this is no longer true - when Apple finally kicked Carbon fully, Qt (IIRC, in 5.13 or something? 5.12 and prior used HIThemes, which was... showing age) switched to rendering true AppKit behind the scenes. There's a few custom controls where they render their own, if no AppKit equivalent exists, but otherwise it's AppKit all the way down.
As someone who used to decry Qt as not native, I'll be the first to admit it's fine now - if something looks "off" on macOS, it's probably moreso the implementing the author doing something different than the underlying framework.
I personally don’t think Qt gives a native feeling in macOS: the look is similar, but the feeling when I get using it... isn’t macOS. Like Emacs style keybindings isn’t supported, I think it’s because the textfield doesn’t get a first responder status... (which is pretty free when programming Cocoa directly).
However I do agree that Qt is much nicer than before, and I can live with them: it’s not like a GTK app in macOS. Qt is def. an improvement compared to the very minimal libui. I’m very excited about that, and so I should get along :-)
Hm, are you sure about that? The documentation[1] for 5.14 still says it uses HIThemes for drawing:
"As with Cocoa and Carbon, Qt provides widgets that look like those described in the Human Interface Descriptions. Qt's widgets use HIThemes to implement the look and feel. In other words, we use Apple's own APIs for doing the rendering."
I guess the documentation could be outdated, but changing over from drawing native-looking widgets to wrapping native widgets (like wxWidgets, SWT and libui) sounds like a big and fundamental (and likely incompatible) change, especially since Qt doesn't do this on other platforms. The release notes[2] don't mention any rewrite of the Mac widget implementation.
You're right that we no longer use HITheme to render the macOS style for Qt Widgets, we use AppKit. But it's used to render into pixmaps, so we're not actually wrapping native NSViews.
My knowledge of that came from digging through the source code over the course of the changes. Great to hear from someone more involved with it - and also, great job on the approach, really glad to see it!
Impressive project, especially for a high schooler! Congratulations on the release of v2!
I have been very impressed with how well an existing React Native app can be ported to Electron via react-native-web - I’ve done this for a couple of apps with quite bespoke UIs and it worked almost seamlessly - the main work was tweaking some stuff which used “onTouchX” events to also support mouse.
That said, Electron of course comes with an overhead that may not be suitable for every project, so it’s great to see work like this going on!
I've been tinkering with React Native and it looks like you can do something quite similar to Proton Native here, while also targeting mobile platforms. Here is how you can cover the gamut of platforms:
- iOS and Android - React Native
- Web - React Native Web
- macOS - Apple's Project Catalyst (run iPad apps on macOS)
- Windows - React Native Windows by Microsoft
- Linux - none yet, you could use Electron but that's undesirable
Perhaps one could instead use Proton Native for desktop and React Native for mobile, I wonder what the code sharing capabilities are for that.
The reason I did not add a renderer to React Native and went with my own renderer and reconciler was because mobile and desktop behave differently. The goal of the project is to make sure you can copy almost all your code from React Native, but not hinder usability. For example, you can define multiple windows in Proton Native and I intend to add more props to that soon.
Amazing work, I am very thrilled to see such an evolution. I remember being frustrated during the early stages of the project and now it works seamlessly, looking forward to the wxwidgets backend, will drop one PR or two if I have time between school and my own personal project. Kudos to you.
If this is qt and wxWidgets, how is this "native"? It's as much "native" as React "Native" is on either iOS or Android.
"Native" means native to the ecosystem it runs on. The gifs on that link show nothing like that. The amount of work that would be required to make even a small app that truly feels native on macOS or Windows would be enormous.
wxWidgets is native - it's simply a thin, cross-platform wrapper on the actual UI from the underlying system. No interface controls are reimplemented unless strictly necessary.
Simply using native widgets is not enough. A "native" app has to feel like a first class citizen in the ecosystem it is running. Achieving something like this with Proton is a tall order.
Native doesn't always mean that. It often just refers to a simple technical distinction of native vs web. Sometimes it also refers to a certain 'feel'. Depends on context.
> Achieving something like this with Proton is a tall order.
That's kinda obvious since Proton just uses wine under the hood. But everything else about what you're running will be native. With wxwidgets it will use true Windows widgets as reimplemented by wine.
After a long time, Proton Native V1 was starting to show it's age. So I ended up making a complete rewrite that includes a lot of the most requested features including flexbox, styling, hot reloading, and components with the same API as React Native.
For those of you who value native components, I've also been working on an experimental wxWidgets backend. There are only a few components, but I hope to implement all the components of the Qt backend soon.
Let me know of any questions you have and thanks!
Previous discussion: https://news.ycombinator.com/item?id=16978901
Congratulations for the v2 release!! I still couldn’t try out right away as I’m on macOS + node v13... but I’ll gonna install nvm as fast as I can :-) Thanks for your great work, it’s super useful for everybody.
I’m still kinda sad about the fate of libui— it was a great project to implement UIs, but Qt was a reasonable point, I think. I’m very looking forwards to the wxWidgets backend...for the true native widgets and the benefit it provides.
Thanks again for your great work on proton-native!!
That sounds like the way to go for a near 1:1 port of a cross-platform desktop app for React-based apps. Also the move from libui to Qt for the UI backend sounds interesting for this project to be used as a lightweight alternative to Electron.
To be a true alternative to Electron one must provide a simple migration path for existing Electron apps to Proton Native which would change everything in cross-platform desktop app development.
That only makes it an increasingly attractive alternative for those who already have an app built on Electron, and has little to do with whether Proton is a “true alternative”. If it can viably permit developing an app without Electron, it’s a true alternative. How easy it is to migrate an app from Electron is a separate matter.
My main question is about app size. Once one has fully built an app and is ready to distribute it to users... how does the file size compare to an Electron app?
In the case of macOS, this is no longer true - when Apple finally kicked Carbon fully, Qt (IIRC, in 5.13 or something? 5.12 and prior used HIThemes, which was... showing age) switched to rendering true AppKit behind the scenes. There's a few custom controls where they render their own, if no AppKit equivalent exists, but otherwise it's AppKit all the way down.
As someone who used to decry Qt as not native, I'll be the first to admit it's fine now - if something looks "off" on macOS, it's probably moreso the implementing the author doing something different than the underlying framework.
However I do agree that Qt is much nicer than before, and I can live with them: it’s not like a GTK app in macOS. Qt is def. an improvement compared to the very minimal libui. I’m very excited about that, and so I should get along :-)
"As with Cocoa and Carbon, Qt provides widgets that look like those described in the Human Interface Descriptions. Qt's widgets use HIThemes to implement the look and feel. In other words, we use Apple's own APIs for doing the rendering."
I guess the documentation could be outdated, but changing over from drawing native-looking widgets to wrapping native widgets (like wxWidgets, SWT and libui) sounds like a big and fundamental (and likely incompatible) change, especially since Qt doesn't do this on other platforms. The release notes[2] don't mention any rewrite of the Mac widget implementation.
[1] https://doc.qt.io/qt-5/macos-issues.html
[2] https://doc.qt.io/qt-5/qt5-intro.html
My knowledge of that came from digging through the source code over the course of the changes. Great to hear from someone more involved with it - and also, great job on the approach, really glad to see it!
Well done!
I have been very impressed with how well an existing React Native app can be ported to Electron via react-native-web - I’ve done this for a couple of apps with quite bespoke UIs and it worked almost seamlessly - the main work was tweaking some stuff which used “onTouchX” events to also support mouse.
That said, Electron of course comes with an overhead that may not be suitable for every project, so it’s great to see work like this going on!
I hope this gets more traction than the react-desktop project.
Super curious: How does an app built with Proton Native fares against an Electron base app when ti comes to RAM and CPU?
- iOS and Android - React Native - Web - React Native Web - macOS - Apple's Project Catalyst (run iPad apps on macOS) - Windows - React Native Windows by Microsoft - Linux - none yet, you could use Electron but that's undesirable
Perhaps one could instead use Proton Native for desktop and React Native for mobile, I wonder what the code sharing capabilities are for that.
There was https://github.com/justinmcp/react-native/tree/ubuntu, but I've long since stopped working on it.
[0] https://github.com/ValveSoftware/Proton
"Native" means native to the ecosystem it runs on. The gifs on that link show nothing like that. The amount of work that would be required to make even a small app that truly feels native on macOS or Windows would be enormous.
Simply using native widgets is not enough. A "native" app has to feel like a first class citizen in the ecosystem it is running. Achieving something like this with Proton is a tall order.
That's kinda obvious since Proton just uses wine under the hood. But everything else about what you're running will be native. With wxwidgets it will use true Windows widgets as reimplemented by wine.
It's actually mad easy in AppKit.