Sciter, the 5 MB Electron alternative, has switched to JavaScript
terrainformatica.com
terrainformatica.com
The issue is that this isn't actually an Electron alternative; the author is upfront about this not actually being a browser-compatible rendering engine. It's just a rendering engine that happens to use some subset / superset of HTML, JS and CSS, but it is not compatible with web libraries and components.
As a basic example, SciterJS crashes loading the "hello world" ReactJS project (at least it did last time I tried it - the author recommended I used a custom version of React he publishes). It's perfectly fine to come up with a lightweight cross-platform UI rendering engine (we know we need more of those), but having it web-adjancent while not really web-compatible is a recipe for frustration.
Any pointers to discussion on what JS/DOM features it's missing that React needs?
- VueJS works as it is.
- PReact works as it is, also with built-in JSX support of Sciter: https://github.com/c-smile/sciter-js-sdk/blob/main/samples/p...
- MithrilJS also works as it is.
- Svetle also works: https://sciter.com/forums/topic/svelte-sciter-js/
Exactly. What's the point of using HTML/CSS/JS for a desktop UI, when you can't make use of the incredible amount of effort that has been spent on frameworks, toolkits, and libraries to make building a HTML UI bearable?
You can re-use components though like LifeletJS : https://sciter.com/sciter-js-runs-leafletjs-as-it-is/
But use of component frameworks have problems. Usually browser window spans whole desktop. But desktop application as a rule do not. Check this discussion: https://sciter.com/forums/topic/what-js-framework-is-prefere...
It is not a a custom version of React but rather extension of DOM model by just these:
1. Native JSX support. In Sciter QuickJS was extended to support JSX literals out of the box: https://github.com/c-smile/quickjspp/blob/master/quickjs-jsx...
2. Native methods:
- Element.patch(...JSX expression...) - native VDOM reconciliation implementation.
- Element.append/prepend(...JSX expression...) - DOM population by JSX
- Native support of lifecycle "events": componentDidMount/WillUnmount and componentUpdate.
Surprisingly, these are enough to allow to use pretty much all ReactJS functionality, and with native speed. And without the need for any external libraries. Check: https://github.com/c-smile/sciter-js-sdk/tree/main/docs/md/r...Rrrright....
It also makes skills non-transferable for the millions of web developers out there. Imagine hiring a SQL expert for your project that uses SQOL which is almost SQL but not quite, so everything they learn won't be useful in their future SQL jobs and the quirks / differences will make them pull their hair out and call it quits in short time.
It almost feels like building an entirely new language would be a better choice (maybe TSX+CSS, with no HTML) to reduce frustration if nothing else.
I appreciate the work you're doing on this project, as always.
Basic skills are very much transferable between e.g. Ruby and Python, despite a ton of differences.
More narrowly, skills are transferable between ReactJS and React Native, despite a ton of component and CSS differences. Skills are transferable between Java-based and Kotlin-based Android development.
So I'd say that a well-defined subset of web APIs, without strategically placed footguns, could be a quite okay target; if code is not directly reusable, it can be easily ported.
You can.
Here is an example of Sciter application that uses RemarkableJS library (https://github.com/jonschlinkert/remarkable) as it is:
https://quark.sciter.com/quark-application-samples/hello-mar...
People upthread are complaining that you can't take some common web libraries and use them in Sciter, but have you given any thought / effort to the opposite? Having a library/polyfill/source translator that allows you to use sciter code in the browser?
It's not the only alternative to Electron, but it might be one that offers predictable and repeatable results.
I released a small open source project on HN last week (https://github.com/Fusion/pngsource) and I wrote its backend logic in Go. I built the frontend using Tailwind (https://tailwindcss.com) and DaisyUI (https://daisyui.com) and, using Go compiler flags, I can release the app using both WebView (github.com/webview/webview) (which, yes, does require the host OS' collaboration) and Wails (wails.app) (which also does.)
On Linux/AMD64, the binary's size is 3.7M when building for WebView, and 6.8M when targeting Wails.
The way the app works is I drag/drop files to the UI, magic happens, and I use github.com/ncruces/zenity to prompt the user for a save location.
I cross-compile the apps using xgo (https://github.com/karalabe/xgo)
It's been working pretty well on Linux, Windows, MacOS. I think WebView's approach of limiting the feature set is working well as it feels more "native" than Wails (better refreshes and resize operations for instance)
However, I already have a few tickets reporting that, for instance, the app is displayed as a blank window in some environments. And it's hard to debug remotely, obviously. So, this is where Sciter may be a better option.
it's not embeddable and not portable, therefor doesn't qualify as a proper GUI toolkit, at best it is a plugin toolkit for windows's integrated web browser
It's basically the same offer java gave the world: write on e, test everywhere.
Oh. That's the QEMU/FFMPEG Fabrice Bellard? That sounds definitely interesting. (Perhaps more than the actual article, haha.)
In my opinion, there are 10x developers, there are 100x developers, then there is Fabrice Bellard.
His/thier history is documented on Wikipedia, but its possible just one representative has shown up to events in the past.
Even for a small team the output would be incredible, but I choose to believe it is just one super-human. One day I hope to meet him.
Just in case, most of JS implementations are one-man shows.
The Sum Of All Men.
When I look at all the "Kinda interesting" projects on my hard drive that died out halfway-through, and compare myself to Fabrice, I think that Fabrice is merely:
- One of the least lazy people ever
- Mentally healthy
- Not publishing small projects he does for himself
- Able to consistently pick projects that are both useful and clearly-scoped.
The project-picking trick is, make programs that work on existing data.
When I make a game, 100 hours of work does not yield even 1 hour of good gameplay, and the game doesn't do anything but let you play the game.
But when Fabrice makes QEMU, there is already a bunch of OS images you can try out in it. When he makes ffmpeg, there is already a bunch of media files to decode and transcode with it. When he makes JSLinux, there is already Linux stuff to play with. And QuickJS runs existing JavaScript code.
Being too original sinks a project. Every time you see a fun project like "I made my own virtual machine, OS, and language," remember, that project is a game, which provided 100 hours of fun for the developer and maybe 1 hour for you. The game is self-contained and doesn't gain any value by inter-operating with the rest of reality, because the VM, OS, and lang are all one-offs.
Fabrice isn't held back by the idealism of "I'll rewrite the world all at once". His stuff is great because he's replacing individual components with stuff that works better, in the same machine. Like GNU did.
The interesting part, me being dumber, how much of could I accomplice assuming the same level of dicipline and similar routines?
Refactoring tons of code gets you used to seeing these patterns, but he is operating at a much higher level of abstraction.
But I didn't know he did a fast JS engine, that looks great
It's kind of inevitable that this happens every once in a while, really.
Mind providing the link? I'd really love to follow that discussion to gain a little more context for this discussion.
Edit: is this the link? https://news.ycombinator.com/item?id=20411154
E2: Nm, that link is old (2019), but still a very interesting read.
/s
DO:
- Use LGPL or GPL for TIScript, if you want; customers who need something further away from copyleft on the spectrum of open source can continue paying
DON'T:
- Equate open sourcing the code with running an open source project and all the overhead that comes along with it and then decide not to do it for that reason; throw it over the wall with a license slapped on it and don't ignore the "NO WARRANTY" section (this is the thing that 99% of GitHub projects with burned out maintainers get wrong)
- Get bashful about code quality and say "I need to polish it up first"; nobody cares (since Sciter has already been shared source for a while, I don't expect this to be a problem, but just trying to cover all the bases here)
The Presto source was leaked years ago. You can't use it for anything you're going to release, of course -- but it's out there.
I have given it a go some months ago, alongside with Delphi and it's really really easy to get started.
It's not open source yet, but... hey! it doesn't have to be to be to be successful.
Of course, Terra Informatica doesn't have the same level of marketing budget than Microsoft/GitHub to promote it as Electron, but a project can rise to relevance by its own merits I believe. I usually err on the side of naïvety for these cases.
CA$ 100 got you immediate access to the source code under GPL or 4-clause BSD, CA$ 500 got you additionally a lifetime commercial license, etc.
One of their customers commented this:
> If people want good software they should pay for good software It’s simple as that.
> I dont care about bloated electron apps. They are competition.
>
> Sciter gives me a competitive advantage and it going open source kills that.
> As a paying customer I hate that.
Above some critical mass of customers, it might be better off not being open source both for its creator and for its users.
It was damned too easy to fix those birth defects of JS so I could not resist to do that right from the beginning ...
JSX is popular enough that it’s safe, ECMAScript isn’t going to break it, but your alterations to JSX are already significantly incompatible: you have <input.search /> being equivalent to JSX("input", {"class": "search"}, null), but the JSX everyone else is using has that equivalent to JSX(input.search, {}, null). I’m not certain if your JSX syntax is supposed to be able to be used with React code or anything else that uses JSX syntax, but if yes then it’ll be broken in a significant number of cases so that it’s worse than useless, and if no, well, it’s going to be misleading, and what if JSX did get merged into ECMAScript in some form? Then you’d be incompatible with ECMAScript again.
Same deal with hyphens in unquoted object literal keys: it’s not part of ECMAScript now, but just because it’d be a syntax error now doesn’t mean it always will be. Decorators in TypeScript are a good example of things going badly wrong even when an extremely popular project is involved.
I say: if you want to go JavaScript, go JavaScript, maaaaaybe plus standard JSX conforming with <https://facebook.github.io/jsx/>, and no further. Even if what you do is obviously superior, &c. &c. I’d apply the same reasoning on your fork of CSS: you introduced it for a good reason back then, but now it’s just friction, even if it’s a little better in a vacuum (and maybe it is in parts, maybe it isn’t in other parts).
You are not obligated to use built-in JSX. TS compiler includes its own version of JSX compiler and so it will not hit built-in implementation.
"Same deal with hyphens in unquoted object literal keys: it’s not part of ECMAScript now"
This was used in TIScript but not in JS, unfortunately.
"standard JSX"
No such thing. Check forst paragraph of https://www.typescriptlang.org/docs/handbook/jsx.html
JSX(input.search, {}, null) makes perfect sense as code and as a concept, though that particular combination of names would be surprising. But suppose it’s something like props.tagName, or library.SomeComponent. As for your JSX(Input-Search, {}, null) being module lookup… I hope that wouldn’t be valid code, and that <Input-Search/> transforms into something other than that, or you’ve got grave problems. But again, this is a point where you’ve deviated from standard JSX syntax in a way that’s far too likely to cause trouble down the road. Why not rather use Module:Component or module.Component, both of which are syntactically valid JSX? (I dunno if these modules are global or have to be imported or whatever, so I don’t know what’s most appropriate.)
Concerning hyphens in keys: I’m referring to what you’re suggesting as a possible addition to your brand of JavaScript. I’m suggesting that it would be better if you resisted the temptation to alter JavaScript at all, beyond possibly standard JSX syntax.
While it’s common to treat JSX as syntax sugar for hyperscript, even that isn’t specified. JSX is a compiler hint with expression semantics, that’s all. You can see how dramatically different it can be in plain JS by looking at compiled output from dom-expressions (most commonly used in SolidJS).
On the Rust side, I've been looking at Tauri, but would much prefer it be usable with something other than the host webview, like Sciter. Tauri offers a bit more of a complete API for desktop apps and it would be nice to have my cake and eat it too.
Even better, a lot of the necessary complexity involved in getting the web stack to look and act like native could be done away with by redesigning a version of that stack optimized for displaying applications rather than documents.
It would no longer be the web stack but it could take the advantages of it without the shortcomings.
See: https://github.com/c-smile/sciter-js-sdk/tree/main/samples/c...
Sciter also supports immediate mode painting on any element (like in DearIMGUI):
element.paintBackground = function(gfx) {
... drawing operations here ...
}
See: https://github.com/c-smile/sciter-js-sdk/tree/main/samples.s...I'm interested in exploring the state of memory management in between pure ownership trees and all-out GC, including stack-allocated structs, refcounting, cycle collection, and per-thread-enabled GCs. I found https://bellard.org/quickjs/quickjs.html and https://news.ycombinator.com/item?id=20413561 when looking for more information on QuickJS's cycle removal, which mentions the "Bacon cycle collector".
https://scholar.google.com/scholar?hl=en&as_sdt=0%2C10&q=bac...
Probably specifically refers to "Concurrent cycle collection in reference counted systems" where Bacon is first author?
In QuickJS:
function Foo() {
let file = new File(...);
file.write("Happy New Year");
}
The file variable (object in it) will be destroyed immediately at the exit from the function.
Which is more suitable in case of Sciter that is embeddable [in native applications] engine.Contrary my TIScript that I was using before had real moving/compacting GC. Objects were freed at GC cycles (in galaxy far far away from invocation).
Now try an data structure, with an unknown size of elements that can non-deterministically scale to several hundreds nodes and delete the graph root node.
Which is why all high performance Ref-counting GC rely on background threads for when RC reaches zero, thus mimicking tracing GC implementations.
"CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”
By the way, C++/WinRT uses background threads to handle cascade deletions of COM references exactly because of this.
E.g. if I want OS-style UI components + styles like a browser tab-strip or pane splitters or toolbars etc?
There are loads of things out there with UI elements, but they seem to be focused on webpage use-cases and design patterns, and so are not really suitable for desktop apps running in sciter/electron/tauri/neutralino/wails/others
The closest thing I know about is https://khang-nd.github.io/7.css/ but that only has a limited control set.
It works with Narrator, NVDA, etc. just fine. HTML may contain standard aria-xxx annotations for better quality.
It's not a complete alternative, so a lot of APIs and features that Chromium has are missing. The Chromium dev team isn't focused on size, but speed and features. While an alternative that does less can focus on size.
Web browser engine is designed with these priorities:
1. to provide safe browsing experience;
2. to present web pages in standard manner;
Note the order. Safe browsing means the following:
1. You must run user facing UI (tab) in separate process. This involves RPC with the rest of application.
2. You cannot allow any executable code other than managed JS. And so you MUST provide JIT or something like that as JS is the only option to run anything.
The order requires and leads to a lot of code to support those priorities.
I seem to remember Sciter being super performant compared to regular web rendering engines.
UPDATE: Now I have read the linked article, here is the reasons (copied from the article):
API and integration principles are close to what TIScript uses – it took me just 1 month to add QuickJS to Sciter core. And 4 months more to expose HTML/CSS runtime to JS.
Relatively compact implementation – QuickJS is slightly more fatty (by 100 kb) but still in acceptable range. For the note: full version of V8 is about 40 mb – 5 times larger than Sciter itself;
Liberal MIT license. Sciter cannot use GPL/LGPL code – many customers expressed this requirement;
Readable source code. Well… almost readable.
"Relatively compact implementation – QuickJS is slightly more fatty (by 100 kb) but still in acceptable range. For the note: full version of V8 is about 40 mb – 5 times larger than Sciter itself"
40 Mb came from Node.JS distribution (V8 + native runtime = node.exe). Sciter is more comparable to NodeJS as it includes good chunk of NodeJS alike runtime too.
Things that are too big are usually composed of smaller things that are also too big.
It is actually not the fact that V8 in context of Sciter alike use cases will be faster.
Consider this statement:
document.body.patch(<body>Hello world</body>);
In case of Sciter this expression runs with native speed. JSX is built-in and element.patch() method is native.While in browser, in case of ReactJS, you will run that patch() (reconciliation procedure ReactDOM.render) with JS VM speed as that algorithm is implemented on JS/TS.
The whole point of Sciter is in its embeddability - you can add native objects of your app callable directly from script. Check this example of native object: https://github.com/c-smile/sciter-js-sdk/blob/main/demos/int...
So you really don't need V8 JIT infrastructure to achieve max performance - just add native objects when needed.
“golden 40 seconds” rule: for the user, to buy a product, it should not take more than 40 seconds from the click on “download” button to the UI to appear on screen.