15 ms·
Thoughts on Clojure UI framework
- Zababa 5y ago> Did I miss something important that should be covered? Accessibility. Outside of that everything seems reasonable. But I don't know much about cross-platforms GUI. I expect someone will come and explain that Delphi or something like that already does everything the author wants except for the integration with Clojure. I would add that I'm not sure which value Clojure provides here. Does the REPL adds anything to the live-reload environment? If not, the choice of Clojure seems to be arbitrary.
- jdminhbg 5y ago> Does the REPL adds anything to the live-reload environment? Yes, altering state in a running application is vastly more productive than save/compile/reload, even if the latter happens automatically.
- dwohnitmok 5y agolive-reload or hot-reload I've seen usually refer to systems that preserve state in a running application (so you're not reloading from scratch). So your application never actually stops running when new code is loaded and you get the same sensation that you're editing the application "in-place." That being said even in that environment having a REPL is nice (although not as much of a quantum leap so much as an incremental improvement) because you can use code to directly poke at your application but is not actually used by your application instead of only being able to write code that your application actually uses.
- brundolf 5y agoI've gathered that lispers have a tendency to say "REPL" when they mean "hot reloading", which causes confusion in discussions like these
- jdminhbg 5y agoI agree that the term "REPL" is poorly chosen, since read-eval-print-loop equally applies to a Bash prompt. But in this case, it's even more than hot reloading, because you are making changes in the running application, not just in the saved source code. With hot reloading, you can change the appearance or behavior of a button and see it reflected immediately. With a Clojure REPL, you can do that but also load in different data, trigger actions, etc.
- brundolf 5y agoThen it's possible an even broader term is needed, but "REPL", to non-lispers' minds in 2021, means narrowly "a prompt where you can type code and then hit enter and see a result". I think "hot-reloading" would be a dramatically more descriptive term even if it isn't perfectly descriptive.
- Guthur 5y agoWe do have a term for it, it's Image based programming. The primary means of interacting with said image is quite often the REPL, and so the two may have become synonymous.
- jdminhbg 5y agoTo me that term also implies that images are the primary means of distribution, as in (most) Smalltalks. That said, it's still probably a better term than REPL for the Clojure experience.
- Zababa 5y agoIsn't "altering state in a running application" precisely how modern live reloading works?
- lilactown 5y agoModern hot reloading and how lispy REPLs work are similar in many ways, i.e. they allow you to make changes to a running application without stopping it, however there are differences in their experience and how they accomplish it. The primary difference in experience is the unit of change that you can make with these systems, which is typically based on the unit of compilation of the language you're using. For example if you're using a language whose unit of compilation is a file, IME you must reload every change in the file at once. This has upstream effects to how hot reloading is accomplished, because if you're reloading an entire file where you've only _actually_ changed one function, then your hot reloading system has two options: 1. It reloads everything in the file, meaning you're potentially losing state that could have been preserved across the change. This typically leads developers to spread definitions across many files in order to be able to make more fine grained changes to their running system. 2. It uses some heuristic to detect whether state should be preserved or not, typically via some static analysis. This can be opaque to developers working on applications, and adds a lot of complexity to the hot reloading system, but is probably the best one can do if your unit of compilation is a file. Lisps, on the other hand, typically make the unit of compilation a "form", i.e. a well-formed syntax tree like (foo (bar baz)). This, combined with some editor tooling, means that I can make extremely fine grained changes to the system by selectively evaluating forms within a file, preserving its state except for the form that was evaluated. The way this works in practice is: I have my editor open and connected to my running application using an extension. I place my cursor on a form I have changed and use a hot key to compile and send that form to the running application. I can view the return value of that form in my editor, and if there were any side effects (e.g. re-defining a variable or function), my application will now exhibit that new behavior. Side note: the benefits of being able to evaluate forms and see their output in my editor is hard to state. It turns your editor from a one-way communication tool (I make changes, hit save, and those changes get made to the application) to a bidirectional tool, where I can both change and inspect the running system. I wish more languages had robust tooling for this. The other difference that you tend to see between languages (even between languages with just hot reloading) is late vs. early binding. Lisps are typically very late bound, so you don't need to recompile and/or restart your entire application on every change. Other languages who bind earlier have to deal with stale bindings. Even JS hot reloading has to deal with this problem in complex ways because most bundlers use closures as modules and bind their inter-module dependencies on instantiation, which means that even though you in theory don't need to recompile or reload anything except the one JS function you just changed, in practice you have to reload the file and any files that depend on it, which puts us back in the position of needing to use some sort of static analysis to detect what has actually changed in order to precisely invalidate application state. I hope this mountain of text helps highlight the subtle differences between hot reloading and a lisp REPL. It's not just the tooling but the specific semantics of the language that make a difference when trying to make changes to a running system. Source: my experience working with and developing tools for hot reloading and REPL development in JS, ClojureScript and Clojure
- amackera 5y agoThe work is funded by a Clojure community group (and a Clojure-using company), and Tonsky has written a bunch of awesome other Clojure (see DataScript[1]). So it seems as though the decision to use Clojure was not made for technical reasons, but it's not exactly arbitrary. [1] https://github.com/tonsky/datascript https://github.com/tonsky/datascript
- Zababa 5y agoYou're right, "arbitrary" wasn't the right word here.
- billfruit 5y agoAlso the ability to ship an app as a single jar, would be great for casual tool making.
- tonsky 5y agoLive reload gets you most of the way for UI programming, yes. REPL is the secret sauce for writing any time of program, not only UI. It lets you explore, play, test, inspect and break things very quickly and without losing context before you find the final shape of your code. I can’t live without it, but it’s hard to explain the benefits to the people who have never experienced it. You have to try it to really be convinced Here is a tiny demo of how I usually use it to build a program https://tonsky.me/blog/interactive-development/ https://tonsky.me/blog/interactive-development/
- Zelphyr 5y ago"The web started to get more suitable for apps probably since Gmail in 2004. It’s very convenient, yet still very limited and has shortcomings." Yes. I worked for over a decade to make web apps behave more like native apps. I finally realized it was a fruitless endeavor. The browser and the web are amazing but, trying to make them behave like native apps just doesn't offer the same experience and, in most cases, offers a worse experience. All one need as proof are all the Electron apps or the Apple Music desktop app.
- brundolf 5y agoWhat? The Apple Music desktop app is native, built with Catalyst (and is awful despite that)
- dboreham 5y agoPerhaps Amazon Music app?
- askonomm 5y agoNative and yet still sucks. Most catalyst apps suck.
- Zelphyr 5y agoIf I'm wrong I'll stand corrected but, it behaves way too much like a web app to not at least be making heavy use of WKWebView.
- brundolf 5y agoWhat does "behaves too much like a web app" even mean in this context?
- jdminhbg 5y agoIf you go to something like the For You screen, you will see a pause while the content is loaded remotely. And if you hit Command-R, it will reload, like a web page. I think the other commenters are right that Music.app is written as a native macOS app, but it definitely leans heavily on web views for content, especially in the streaming parts of the app.
- chrisweekly 5y agoBrilliant! Love it! Good luck! Keep us posted!
- cosmotic 5y agoI thought Swing did an excellent job with native UIs, though it did take some care by the developer.
- brundolf 5y agoIt was slightly before my time so I'm not really sure why it suddenly died. I can say the author's correct that a declarative style has proven to be more productive in the time since, but there was a big gap there between the declarative shift and when swing died off.
- cosmotic 5y agoAs someone who's worked on both declarative and procedural UI, I'd say declarative is harder to work with. It's much more difficult to debug. I think the largest benefit of declarative is that it largely mitigates unresponsive UI code, though that too is pretty easy with a little care.
- brundolf 5y agoI've worked with both too (only really on the web, fwiw) and I have the opposite feelings. It feels like a huge waste of my mental energy to manually keep state in sync across different parts of the app when that's pretty well a solved problem at this point.
- Scarbutt 5y agoWhy use the language with the most horrible startup time for a GUI framework though? The core might be C/C++, but users will write their app in Clojure. GraalVM also still has big limitations.
- nlitened 5y agoAs far as I understand, the core graphics library will be Skia, and it’s C++. So to some extent, your wish has been granted.
- Scarbutt 5y agoWhat wish?
- nlitened 5y agoI am sorry, I mistakenly assumed that you thought it would be better if the new GUI library used some language like C++ instead of Clojure.
- brundolf 5y agoThere would still be JVM startup time even if some parts of the process delegate to native code. Though the OP acknowledges this and still thinks this is the best approach (and plans on mitigating the issue as much as possible). I'm of a similar mind: desktop apps tend to be long-lived and a few tens or even hundreds of milliseconds at startup shouldn't really matter.
- zorr 5y agoJVM startup time is not great but it's not horrible either. Especially in the context of desktop apps that are often started once and kept running for a long time. With some care it is definitely possible to spin up a JVM and display an initialized window within 1 or 2 seconds. Which is roughly the same time as Gimp or Krita or Thunderbird take to startup on my machines. I even have a few git-style CLI tools that bootstrap a JVM on each invocation without using optimized graalvm/native images.
- cosmotic 5y agoI think the article is conflating people's acceptance of web apps with people's appreciation of web apps. Web apps (or electron apps) are always worse than a well-written native counterpart in every verifiable UX metric. Let's not kid ourselves: web apps and electron apps are developer-experience focused, not user centered.
- phyrex 5y agoI believe that’s what the article said too. Where do you see him conflating this?
- cosmotic 5y agoI suppose it might have been what I inferred when the author said "Yet it has been a massive success. I think it means our industry is craving for a good desktop UI framework."
- Zababa 5y ago> Web apps (or electron apps) are always worse than a well-written native counterpart in every verifiable UX metric. That is true. > Let's not kid ourselves: web apps and electron apps are developer-experience focused, not user centered. That isn't true. I spend most of my days on Linux. Before web and electron apps, the alternatives were not well-written native apps. The alternatives were "Use another program". As a user, I'm really glad many things are web-centric these days.
- cosmotic 5y agoI think you're benefiting from the coincidence that developers (managers?) chose Electron + 1 code base and void of well-written apps due to low market share. Sure, an electron app is better than a broken side project. But a fully native linux app would handily beat the electron app. If there were a larger market share, there would be more well-written native apps. If devs focused on users, the easily-ported mediocre electron app wouldn't exist.
- 5y ago
- mosdl 5y agoHates on Electron and bloat, but is fine using vdom which also adds memory bloat? Seems like a wierd combo.
- deleted 5y ago[deleted]
- honko 5y agoI imagine the bloat from a vdom vs the bloat from chromium is somewhat different.
- zerr 5y agoThe bloat from the JVM...
- didibus 5y agoI wouldn't say the OP hated on Electron, they provided criticism: - lack of threads - stuck using JavaScript - can't do your own layout - can't render 144Hz animation - adds 150mb to app bundle - memory hog Apart for the last two, I think he's approach would solve those problems.
- speedgoose 5y agoMy experience playing the Java Minecraft tells me that it's going to be a challenge to render smooth and consistent animations on top of the JVM. The garbage collector tends to create huge frame drops. And 144Hz and more is definitely possible in Chrome/Edge.
- kaba0 5y agoMinecraft is (used to be?) a badly optimized game, you can hardly take away any conclusion from that. And the JVM has multiple of the best GCs out of any runtime, with a specific low latency one which promises <1 ms stops, at which point the OS’s scheduler will have more latency. Also, it’s not like JS is not a GCd language..
- webmobdev 5y agoWhile I appreciate the time invested in researching all this, I feel this is "reinventing the wheel". Native GUIs almost always offer superior performance and already offer everything that the developer(s) of a new framework would have to reinvent. Thus, a wrapper around native GUIs makes the most sense. (GUI frameworks on Linux though does need an improvement or a complete revamp. )
- novok 5y agoIn practice wrapper types have been done many times before, and failed to make something good. Rendering everything yourself is actually as performant or potentially more performant than a 'native' set because what everyone is doing in the end, including native frameworks, is rendering on a rectangle using opengl, vulkan or metal.
- webmobdev 5y agoVCL on Delphi and LCL on Lazarus ( https://www.lazarus-ide.org https://www.lazarus-ide.org ) are pretty neat and feature rich wrappers. It's not the rendering that's the issue - it's the work involved in making them conformant to the different OS guidelines, and dealing with the intricacies and quirks of each OS. It's more practical to extend and enhance what is lacking, rather than rebuild the whole thing again in 4 (Windows, macOS, Linux, FreeBSD) different ways.
- dgb23 5y agoI think the author agrees with you. From the same blog: https://tonsky.me/blog/skija/ https://tonsky.me/blog/skija/
- linguae 5y agoOne question regarding wrappers around native GUIs as someone with little experience writing GUI software: how does the wrapper handle different UI/UX guidelines? It’s one thing to wrap a common button class around Win32, AppKit, Qt, and GTK buttons. It’s another thing to have the application simultaneously comply with the UI/UX guidelines for each desktop environment.
- brundolf 5y agoAs someone who believes Electron is genuinely the best existing option for cross-platform desktop apps (and possibly desktop apps in general), I'm excited to see someone trying to make something better by incorporating that context and that progress instead of ignoring it. The goals and the ideas here sound well-thought-out, and not tone-deaf, and I really hope this goes somewhere.
- diskzero 5y agoOne aspect of Electron app, is that typically you can use the most of the same code in the browser. Would you expect to see the same result from this project; ClojureScript code running in the browser and JVM-backed Clojure running on the desktop? Like you, I am excited to see this approach. There may be a lot of negative opionions about Electron, but you can't deny the inroads it has made.
- brundolf 5y agoIt seemed like the author hinted at that (and I believe Flutter sets a precedent for it), but I have no firsthand knowledge of the project With that said: I got the sense the author is mainly interested in targeting high-complexity desktop apps, which tend to have less need to be available in both forms
- tomjen3 5y agoNow I am curious, why is Electron a better option than putting a simple webserver in your code and then open it in the users favourite browser? You get the same options in terms of what the JS can do, except you aren't limited to Javascript on the backend and you don't need to ship the Chrome runtime to a user that already has one.
- brundolf 5y agoA few things: 1) Packaging/general polish. With the server solution the user doesn't get a desktop icon, or a single .app/.exe, etc. Their window manager doesn't work with the app the normal way. Etc. 2) Certain other native integrations. An electron app can populate the Mac menu bar, it can use native right-click menus, it can do rich notifications that aren't constrained to the browser's notifications API, it can show a red dot in the system dock, etc. 3) Stability of pinning to a specific Chromium version. This can work for some things- mostly developer tools where users may not care as much about polish and may care more about reducing install size. But it's not really a replacement.
- solarkraft 5y agoInteresting that yesterday's submission of this got buried. Let me repeat and elaborate because it's somewhat close to my heart. > I plan to focus on the high‑quality desktop instead of finding a mediocre middle ground between desktop and mobile. Oh god damn it. This space is severely under-served. It's only filled by Xamarin Forms, React Native (kinda), Flutter and web. They all kind of suck for desktop apps. It doesn't even have to do both well. It just has to be a great experience on one platform and an okay one on others. Phone apps can be good desktop apps with minimal modification (as Apple realizes 5 years after Microsoft almost did) and not many things are worse than happening to use one platform and your data/functionality just not being available on it. Stop it, please. Smartphones are computers. They're used for the same things and increasingly so. Stop pretending they're fundamentally different. They're not. Guess why the Web is eating everything. It's WORA. And there's close to no competition.
- Zababa 5y ago> Phone apps can be good desktop apps with minimal modification I don't really agree here. Phones and desktops are very different, and have very different UI needs. > Stop it, please. Smartphones are computers. They're used for the same things, even increasingly so. Stop pretending they're that fundamentally different. Navigating with a mouse and keyboard is not the same thing at all ad navigating with your fingers on a touchscreen.
- solarkraft 5y agoThe UI features required are different, but like on websites, mobile-first works very well. There are some pretty native-feeling Catalyst apps on macOS: Voice Memos (has flaws), Jira (very native feel), Vectornator (pretty full featured and perfectly native feeling Mac app) and even unmodified iOS apps (Metatext) that run great, as well as smartphone-styled Apps (Telegram) that are great to use. Sure. Keyboard shortcuts for text. Right click instead of long press. More precision. Hoveing. Swiping back on the trackpad instead of the screen. There are differences - but they're really not that fundamental. Minimal differences. We can certainly argue about whether mobile first allows an app to use the full potential of the desktop. Maybe not. But I honestly don't care that much if the alternative is no app.
- thom 5y agoI have been enjoying working on a cljfx project recently. Extremely fast to get a prototype together, proper multi core support for number crunching, whole JVM ecosystem to reach out for functionality. Probably not for the faint hearted but it has the advantage that it exists today.
- ducktective 5y ago> Probably not for the faint hearted Any advantages over Qt or Electron?
- thom 5y agoFor a Clojure programmer, yes. And for my particular use cases I’m happy with this over, for example, React Native plus ClojureScript because I can bring in JVM libraries and have easy threading. But if I were starting from a completely blank slate or building a startup around something (especially consumer based) I’d probably make different choices.
- native_samples 5y agoJavaFX is really under-rated. The primary argument against it being pushed by JetBrains seem to be related to exotic text rendering features, and/or bugs. OK, well, it sounds a lot easier to do some targeted upgrades there than throw it all out. The core tech is really solid. It's been neglected in the past few years but desktop tech doesn't change that fast. Throwing out a toolkit designed for complex desktop apps and trying to adapt a mobile toolkit doesn't seem likely to lead to better results.
- thom 5y agoI'll admit I learned JavaFX at the same time as the Clojure wrapper (which fights against the paradigm a little, perhaps) but what I've seen is fine. Big component ecosystem, and styling that appears to be quite powerful if you want it.
- billfruit 5y agoMain thing I feel concerned with JavaFX is that it is no longer being bundled with the JRE. Why is it not being considered a first class citizen of the Java Environment? This means that even the tiniest project using FX should have dependency management to ensure that JRE versions and FX versions and other supporting jars all align up properly to work. Meanwhile AWT/Swing just works right out of the box.
- meowphius 5y agoI read somewhere when someone was criticizing Rust for GUI stuff, that lack of OO and inheritance can be a real problem. Is that also true for Clojure?
- nlitened 5y agoIf I understand correctly, the author talks about pure-data approach to building GUI, and that’s pretty much the opposite of OO and inheritance.
- dgb23 5y agoModern languages like Rust/Go/Clojure typically incorporate polymorphism without the need of inheritance and get more out of it rather than less. The type of polymorphism and malleability you get from Clojure is much more expressive than class inheritance. You're losing the OO mental model, but gain very loose coupling (data coupling) and code that is easier to reason about. (The trade-off here is not for everyone though.) On top of that, Clojure is an extremely flexible, interactive language, which is fantastic especially for GUI programming (as mentioned in the article).
- tonsky 5y agoI am pretty sure it can be worked around or even emulated in Clojure with minimal effort if needed
- zerr 5y agoQt doesn't wrap the native controls, wxWidgets does.
- tonsky 5y agoMaybe Wikipedia article should be fixed then: > Recent versions of Qt use the native style APIs of the different platforms, on platforms that have a native widget set, to query metrics and draw most controls, and do not suffer from such issues as often https://en.wikipedia.org/wiki/Qt_(software) https://en.wikipedia.org/wiki/Qt_(software)
- zerr 5y agoIt's an implementation detail to mimic the platform look. If you don't want that, you can use custom styles/stylesheets. The point is, e.g. QPushButton is not a wrapper around NSButton on mac, or BUTTON hwnd on win.
- zorr 5y agoThis is a great writeup and good to see I'm not the only one looking at JVM for cross platform desktop apps. Recently I've been experimenting with TornadoFX and it is very nice to work with. It's a Kotlin wrapper for JavaFX providing a "declarative builder DSL" to compose views. It uses a MVVM approach where the View components are bound to the ViewModel using observables. JavaFX supports CSS for styling components including variables without the clunky web css variable syntax. And with Kotlin coroutines/suspend functions it's trivial to add async IO for network and disk access. Combine all that with modern JVM and Gradle tooling for native packaging (deb/rpm/msi/dmg) and access to the huge ecosystem of JVM libraries. Of course there are drawbacks. JVM startup time isn't great but even with Spring Dependency Injection my project starts up in under a second which is fine for a long-running desktop app imho. It will never be as fast or consume as little memory as a native toolkit does but to me it's the pragmatic sweet spot in between native toolkits and packaging a full webbrowser like Electron. I'm not affiliated with TornadoFX or JavaFX, just a happy user that has rediscovered joy in building desktop apps again.
- throwaway34241 5y agoFrom "Why not web": > I think the fundamental problem of the web is that its APIs are too high‑level. Frameworks like Flutter (at least one backend) [1] [2] and Gio [3] use low-level APIs like WebGL and WebAssembly. That might not be the right choice for a web-first framework but seems reasonable for apps that would otherwise be desktop-only and need low-level access to be compatible with the native version. It looks like he's using Skia for rendering so the WebGL/WebAssembly Skia port that Flutter uses might be a particularly good fit. I assume a Clojure project would use Clojurescript if it had a web target, but I'm not familiar enough to know if the Clojure/Clojurescript differences [4] pose a big obstacle for this sort of UI framework or not. [1] https://flutter.dev/docs/development/tools/web-renderers https://flutter.dev/docs/development/tools/web-renderers [2] https://skia.org/docs/user/modules/canvaskit/ https://skia.org/docs/user/modules/canvaskit/ [3] https://gioui.org/ https://gioui.org/ [4] https://clojurescript.org/about/differences https://clojurescript.org/about/differences
- tharne 5y agoThis is really cool. It's great to see someone pushing for good desktop applications. I'm not an electron hater, but I don't love it either, and I'm happy to see new alternatives emerge, in a fun language like clojure no less.
- webmobdev 5y agoFree and open source: https://www.lazarus-ide.org/index.php https://www.lazarus-ide.org/index.php Other 30+ cross-platform GUI toolkits / frameworks: https://www.slant.co/topics/983/~best-cross-platform-gui-toolkits https://www.slant.co/topics/983/~best-cross-platform-gui-too...
- pkphilip 5y agoSadly Lazarus and Delphi don't get the attention they deserve. Writing even a sophisticated app in either of these platforms is a pleasure.
- dvdkon 5y agoMaybe it's a question of personal taste, but Pascal (in any of its newer forms) isn't a langauge I like working with. Up-front variable declaration, verbose flow control, next to no support for functional programming... LCL is nice, I especially like how small the result is, but in the last ~30 years, programming language design has progressed a lot and Pascal just seems archaic, and not in a good way. Modern PL design isn't just about "syntax sugar" as the FreePascal community would have you believe.
- pkphilip 5y agoYes, it does come down to personal taste and also programming style. Not everyone wants or needs functional programming.
- pgt 5y agoGo go go Nikita! If there is anyone in the Clojuresphere who could pull this off, it is Tonsky.
- tonsky 5y agothank you!
- creamytaco 5y agoYou criticize Electron and then proceed to make pretty much the same mistake by using ... JVM. I don't think this is going to fly as a better alternative to JavaScript. It's just one evil exchanged for another. And I'll be extremely surprised if you manage to do smooth animations at 144Hz in Clojure without killing battery life.
- elias94 5y agoClojure ecosystem really need something similar. The ability to not have to deal with Clojuscript and to pack-ship an app with desktop UI easily. With the work you did on Skija we have high hope! Good luck and keep us updated
- Tarucho 5y agoGUIs are one of the domains where object orientation shines. The ability to express in code a set of physically bounded widgets with visual a representation that matches their state is probably a biggest win for OOP. FP, I guess its not that intuitive.
- tadfisher 5y agoCompose is still data-oriented! It's not only possible to pass a Button around, it's encouraged. The representation you should pass is a higher-order function, or lambda: val button: @Composable () -> Unit = { Button(...) } List(button) // definitely possible The advantage is encapsulation: Button as a lambda exposes no external state, so you don't create tangled graphs of data dependencies in your UI. You should definitely take another look at Compose, because this concept maps extremely well onto Lisps in general (code is data) and Clojure in particular (tight composition of immutable state).
- tonsky 5y agoI find encapsulation more of a disadvantage than advantage. I want access to internals when I need to. Passing lambdas is not data-oriented, and it does not help to prevent tangled data dependencies
- chrismorgan 5y ago> [Electron] can’t […] render smooth 144Hz animations Hmm? I’m on a 165Hz screen, Arch Linux/Sway, and Firefox and Chromium both do 165Hz just fine¹, both with CSS animations and with JavaScript requestAnimationFrame. I would expect Electron to behave the same way. To be sure, you’ll have to be a tad more careful at higher frame rates, but my point is that it can render smooth 144Hz animations. — ¹ When run under Wayland; XWayland is apparently still locked to 60Hz.
- dmitriid 5y ago> but my point is that it can render smooth 144Hz animations. It can't, generally. There's a specific subset of animations that browsers can offload to the GPU: anything that doesn't touch the layout. So, transform/translate. That's it.
- chrismorgan 5y agoOpacity and affine transformations cover most animations that people want, though certainly not all. SVG is also generally more amenable to GPU powering. (And if they’d catch up with Firefox’s WebRender, then even more would be done on the GPU.) Beyond that, though, you’re underestimating what browsers are capable of. You’ll certainly hit limits much sooner, and it’ll be more sensitive to other system load (thus more prone to jank), but it’s not hard to drive layout-affecting animations at 144Hz provided you careful about isolating the affected areas. The “don’t touch layout, animate transformations” narrative that got pushed hard some years back was much more about mobile than desktop—desktop can be more efficient with transformations, but even layout-based animations will generally be smooth on desktop platforms. (In the past, Firefox struggled more than Chrome on those sorts of things, but WebRender has helped to completely reverse that.) As an absolutely toy pathological example, on my admittedly powerful laptop (Ryzen 5800HS, using integrated GPU) in Chromium (since we’re talking Electron and not WebRender), moving a series of ten inline-block 80px emojis by setting their margin-left to random layout-dependent values every frame (so that’s ten forced relayouts per frame, and quadratic layout behaviour) tends in profiling to take around 3–4ms, occasionally spiking briefly just above the 6ms budget my 165Hz display gives and causing jank (… not that I can tell visually with the emoji flickering all over the place anyway, but the profiler tells me!). For comparison, just one emoji (dodging the quadratic stuff) tends to take around 1ms, showing that a lot of the costs here are constant. URL for the code: data:text/html;charset=utf-8,<style>body{overflow:hidden}div{display:inline-block;left:0;position:relative;font-size:5em}</style><div>%F0%9F%99%82</div><div>%F0%9F%99%81</div><div>%F0%9F%A4%A8</div><div>%F0%9F%98%AE</div><div>%F0%9F%98%9B</div><div>%F0%9F%98%80</div><div>%F0%9F%98%86</div><div>%F0%9F%98%A2</div><div>%F0%9F%98%95</div><div>%F0%9F%98%92</div><script>function f(){document.querySelectorAll('div').forEach(e=>e.style.marginLeft=Math.random()*(innerWidth-e.offsetWidth-e.offsetLeft*0.1)+'px');requestAnimationFrame(f)}requestAnimationFrame(f)</script>
- billfruit 5y agoWill it support shipping apps as a single jar?
- tonsky 5y agoIt should. I plan more traditional packaging (exe/app) too, but jar will probably be the first option before that
- czabaj 5y ago> CSS in JS as a good idea (we won’t start from CSS separated from layout, but it’s good to not to repeat HTML’s mistake). The HTML and CSS separation is great for accessibility. It is also great for machine processing. On the web "content is the king" which might not be true on native apps, but I tend to feel that separation of content and its _visual_ appealing is a good thing in general, only if CSS would have substantially less quirks.