Hacker News new | past | comments | ask | show | jobs | submit login
Building a hackable editor in the browser (bjenik.com)
112 points by bjenik on July 14, 2019 | hide | past | favorite | 72 comments



So AFAIK Electron is built on V8 JS engine. Last I looked that has a JIT compiler, then I’d expect performance to increase as that ‘warms up’


It does, but you've still got to keep around the optimizing JIT compiler, its JavaScript metadata, and a hundred other things around even after the JavaScript has been partially compiled to native code.



Could someone upgrade/update the link to include https:// please?


    script, style { display: block; }
I have no words.


This is a discussion forum. Putting things into words is the purpose of commenting. If you can’t, then maybe you shouldn’t.


I did put something into words, didn't I? ;)

Joking aside, I would have thought this was possible.


*never thought


As siblings have commented, it's not clear what reaction is obscured by your lack of words; but, if it's a veiled comment on the inadvisability of doing this, the author beat you to it:

> Warning: All of this doesn’t really follow any best practices for working with html, css or javascript - on the contrary: what we will be doing may look horrible to some people, and rightfully so - so you may not want to try those things at work just yet.


I do - that's great fun. I'm actually a bit surprised that the browser bothers to add text nodes to the DOM tree as normally there wouldn't be any reason to, but it's great to learn that they do, and might be something I'll have a play with one day.


Yeah, I've been writing CSS and HTML for over 20 years and I would have thought these tags were in the actual DOM and could be rendered.


You would or would not have thought? I suspect you forgot a negation.


Thanks, yes I forgot "never".


I was very surprised as well. It’s pretty awesome isn’t it?


Why? What do you mean? Just curious!


I interpret this comment by how I feel about the idea. I have no words to describe how awesome a hack this is!


Why don't you try - because this comment has no value. If you don't like this for some reason, please state why.


nice, I did something similar to myConsole, except I did override some functions and added some buttons to make it look like and app

https://github.com/victorqribeiro/myConsole


Yeah, so it's basically emacs in the browser!

Changing editor capabilities on-the-fly!


...how about moving things out of the browser? It's cramped as it is. And then people wonder why their browser is so slow... "it's just displaying documents!"


For that we’ll need an adequate cross-platform (-ish) way of doing UI. I’m not a fan of React Native, but it seems to be the technology we’re looking for, though it doesn’t seem to be as ready for the desktop yet.

An all-native solution on top of a powerful modern language (rust?) would be ideal, but that doesn’t seem to be the direction things are moving. We’ll probably end up with Flutter/Native.


Yes that would be awesome!

Unfortunately the providers of the OS'es we use don't bother with this.

What would the world be like if you could run anything anywhere and most importantly: how would you decide that you prefer a mac to a windows-machine?

I think web technologies are a bridge that many like to use because of the sad state of things in the UI domain.


Microsoft maintains it's own fork of react-native that allows this. https://github.com/Microsoft/react-native-windows

There's more experimental forks for macos and qt.


Flutter isn't "native" as you would use that word in the context of UI design toolkits.


Flutter is drawing a native style UI elements on an OpenGL (like) surface, and that is pure binary running on the device processor. Platform-specific features like Bluetooth, WiFi, etc. are bridged just like in ReactJs.


"Native" in context of UI toolkits is "using system-provided UI controls through system APIs". The opposite of that is drawing your own controls, which then usually don't integrate well with the OS and don't support the interoperability and accessibility features that are expected of UI controls on that OS.


That's what native used to be, but nowadays it's "not electron". Qt or wxWidget apps are considered native as well.


> That's what native used to be, but nowadays it's "not electron".

This makes me sad. Coherent UI is a very important point to users IMO. Users can assume that some special feature from App X will also work on App Y.

(It also allows OS/GTK/Qt devs to enhance UX without application modification.)

For example, in macOS Cocoa, textboxes have universal readline-esque keybindings (and is configurable globally) which, as an Emacs user, very, very useful.

Most Mac apps use Cocoa as the GUI toolkit, so basically all kinds of apps can benefit these keybindings.

Another example of this directly benefiting users is the addition of tabs in macOS Sierra(I’m not sure about the exact versions :-().

macOS Sierra added tabs to Cocoa apps, and applications could get the feature without additional modification. (I’m not sure if it’s absolutely none or if recompiling was needed, but I think it’s the former.)

I could use tabs in any application, with the same look-and-feel, in all apps!

And, don’t forget accessibility here!

Stories like these are mostly only macOS; since Windows apps usually just re-invent all kinds of UI elements, while Linux’s GUI toolkits are super-fragmented. (GTK vs Qt is one thing, and there are lots of other options!)

We really should be trying to use the native GUI toolkit (and that is why I’m hoping cross-platform native UI libraries like libui succeed), not using some Flutter-esque library that draws everything from scratch.

(BTW, AFAIK wxWidget tries to get this right and tries to draw things using the native toolkit.)


> macOS Sierra added tabs to Cocoa apps, and applications could get the feature without additional modification. (I’m not sure if it’s absolutely none or if recompiling was needed, but I think it’s the former.)

Tab support was added without linking against the new SDK: apps would get it "for free" when running on macOS Sierra.


> Tab support was added without linking against the new SDK: apps would get it "for free" when running on macOS Sierra.

Yeah, right. I remember being very happy as some of my not-worried-about-mac applications (it's a word processor that uses a special format only used in our country) had tabbing enabled. :-)


So Java is native now?

I think a simpler and easier approach is to simply wait until the inevitable next desktop disaster so that we can call Electron native.


Qt is decidedly not native, but can attempt a "native look-and-feel".

wxWidgets actually wraps native GUI widgets though...


I've been thinking a lot about this lately and I'm trying to compile some information on how others think it should work.

Can you elaborate on what you mean by an all-native solution on top of a powerful modern language?

The way I see it is that a new toolkit like GTK or Qt is required in the target language.


> The way I see it is that a new toolkit like GTK or Qt is required in the target language.

The way i See it is that a new toolkit like GTK or Qt is required in C so that it can interface with any language as to avoid unnecessary duplication between languages (it is much easier to convince people switch toolkit than switch programming languages), ensure no language-specific indirect dependencies (especially if it is to included in OSes like OpenBSD that are traditionally C oriented) and with a stable backwards compatible ABI to avoid wasting the time and effort of whoever maintains the bindings (no need to rewrite them every few years), whoever decides to learn the new API (no need to learn something new for doing the exact same thing as before, only now in a slightly different yet incompatible way) and perhaps hopefully become a "standard" API people can target on Linux without having to carry 29892482923TB of libraries for a trivial app since you cannot rely on anything outside of X11 being there (and if GNOME people have their way, you wont be able to rely on even that). And of course all that in a permissive license that leaves everyone happy.

Now guess how likely all of this is going to happen.


> and perhaps hopefully become a "standard" API people can target on Linux without having to carry 29892482923TB of libraries for a trivial app since you cannot rely on anything outside of X11 being there

so, uh, what would you depend on ? at the bare minimum you would need, for a gui toolkit :

- dependencies to X11 (xcb) and wayland (and cocoa and win32)

- dependencies to xkb, etc.. for keyboard handling

- dependencies on ICU for unicode text handling

- dependencies on freetype, fontconfig, harfbuzz, pango, etc... for font rendering

- dependencies on GL to allow your users to have a GL viewport, and potentiall on a software implementation of GL on windows because yes, even in 2019 this is still a problem on some user's computers

- dependencies on cairo, skia, QPainter, or something like that to provide a canvas-like API

- dependencies on libinput because that's the modern way to get mouse input on linux

- you are going to want a library of useful datastructures that aren't provided in C -> dependency to GLib or something else

- dependencies on libpng,jpeg, etc.... because you want your users to be able to have images in their app

- dependencies on dbus to be able to provide desktop notifications, etc

and you aren't even starting to match all the useful functionalities of GTK & Qt


Of everything that list all you really need is the X libraries and you do not need to carry (meaning distribute) those since they are part of the every single desktop environment and have a stable ABI. The rest aren't strictly necessary, but i think Cairo has a stable ABI. I'm not sure if it is available everywhere though. OpenGL (and Vulkan) can be provided via dynamic linking, though only via an API that doesn't guarantee its existence (it doesn't exist in all X11 desktops - AFAIK Raspberry Pi doesn't support them).

In any case, the dependencies i mean here are dependencies for the applications that target your API, not the dependencies your API has. You can make your API use whatever library you want to -e.g.- load PNG, JPG or whatever, but that can be hidden from the user of the API (ie. their binary will link against libyourapi.so.1 for yapi_load_image and what that specific version of libyourapi.so.1 uses to load the requested image is an implementation detail).

Note that this is in the context of making that API a standard people can target, not a reusable library (and its own dependencies) people carry with their binaries. Basically the equivalent of how you do not need to give USER32.DLL on Windows to your users because you can pretty much expect that it will be there.

Nowadays the only equivalent on Linux is the X libraries, anything else is either not guaranteed to be there now, or not guaranteed to be there in ~5 years because thanks to CADT people cannot stick with an API and feel the need to break everyone's programs to feel useful.


> Of everything that list all you really need is the X libraries and you do not need to carry (meaning distribute) those since they are part of the every single desktop environment and have a stable ABI.

both Debian and Fedora use wayland by default now. And wayland alone only gives you the ability to open a viewport, so you are going to need a lot of stuff if you want your UI library to do something as simple as :

    #include <linux_ui.h>
    int main() {
        linux_window* window = linux_ui_create_window();
        linux_widget* label = linux_ui_create_label(u8"お早う御座います");
        linux_ui_widget_set_parent(label, window);
        linux_ui_widget_set_pos(label, 50, 50);

        return linux_ui_process_events();
    }
> Note that this is in the context of making that API a standard people can target, not a reusable library (and its own dependencies) people carry with their binaries. Basically the equivalent of how you do not need to give USER32.DLL on Windows to your users because you can pretty much expect that it will be there.

But almost no one makes Win32 apps with the Win32 API anymore anyways. The majority of desktop windows apps created today are using WPF or UWP which does not use any "native" stuff (that is, the win32 UI API), Qt or Electron. If this model does not even work on windows, why would you want to port it on linux instead of letting people ship their app as they wish ?

> Nowadays the only equivalent on Linux is the X libraries, anything else is either not guaranteed to be there now, or not guaranteed to be there in ~5 years because thanks to CADT people cannot stick with an API and feel the need to break everyone's programs to feel useful.

Even if someone made this magical new library today, I would still have to package it along with all its dependencies in an AppImage because I have users still on ubuntu 12.04, 14.04, and 16.04 as well as debian stretch and jessie.


I meant something like SwiftUI, but as an abstraction over platform-native components like React Native. By Flutter/Native I meant Flutter ported to a language without garbage collection and with ability to easily call into C libraries.


Maybe libui can be of use? As far as I know they wrap native element but I have not looked into it much.


What about libui?


My browser is not slow, for me starting and using a lot of desktop apps feels slower than browser apps to be honest.


Your slow desktop app is an electron app


I was going to comment this. Typically these days a LOT of Desktop apps are Electron based:

VS Code, Slack, Signal, probably Keybase, Skype, MS Teams, Discord, RamBox, IRCCloud, Postman, Insomnia, Light Table, Hyper, and...

The list goes on.

But those are apps I have used and know are Electron. Thats at least 10 different instances of Chrome on a system running at any given time.


It’s only ten instances of Chromium if you actually run all ten apps at any given time!


Which is like, the reason people invented multi-tasking operating systems, somewhere around 1960s.

Which is why current disregard for application performance really irks me. A computer is meant to run a lot of things at the same time. To some point, the utility of a computer scales with the number of things you can run simultaneously on it. Your Electron chat client that thinks it own 100% of CPU and RAM essentially puts a soft limit on that. It's less of a problem for power users, who know how to work around such problems, but it is a deal for regular people, who'd love to run a few things at a time but can't, because one or two apps grinds their cheap computer to a halt.


No, my fast app (VSCode) is an electron app. Steam is slow, Photoshop is slow, SourceTree is slow.


If you think you browser is fast, you'd be blown away by any decent application.

Too bad all apps are now electron.


> If you think you browser is fast, you'd be blown away by any decent application.

In data centers, loading data from networked server, where it's in memory, can be used over loading data from a disk, because disk is comparatively slow.

A web app can load JavaScript assembler, which isn't much slower than a desktop app written in C.

Bigger - and slower - parts of the web app can be loaded after the app starts interacting. So - at least in principle - no sizeable speed difference, which would blow somebody away.

Advantage of web app is cross platform uniformity. Write once, run everywhere.

Of course, reality can make adjustments, but we can see and invent things.


This is misleading as all get-out. "JavaScript assembler" is WASM, I assume? Running it in a browser still includes the overhead of a browser. The slowness is not from the wasm runtime (which has been implemented standalone and is fast), but in the browser-y gui stuff (which is what electron is good for). Also, WASM has less tooling etc. around it than JS, so JS is used for now. And jS is slow, but it's what is used by electron.

Your saying "electron could be made faster if we did all these huge things" is like me saying "but the c could be faster if we did great threading, really efficient code, inline ASM, and used intel's crazy compiler for maximum optimization". I get there's hope for the future, but not currently. In any case, implementing a custom graphics stack (like the web) will always be a heavy-weight task compared to one application.


> The slowness is not from the wasm runtime (which has been implemented standalone and is fast), but in the browser-y gui stuff

Not entirely true: In representative benchmarks, WASM has only 65% of the performance of native code. Of course, everything gets much worse the moment you interact with browser mechanics—WASM is only this fast while doing raw computations.

https://www.usenix.org/conference/atc19/presentation/jangda


> In data centers, loading data from networked server, where it's in memory, can be used over loading data from a disk, because disk is comparatively slow.

Most people however don't live in a data center. On regular computer and with regular Internet connection, even spinning rust blows the network out of the water. And computers increasingly ship with flash memory these days.

> A web app can load JavaScript assembler, which isn't much slower than a desktop app written in C.

A desktop app has already loaded that assembler at build-time, and when executed, it loads and runs native code.

(Well, sorta. Scripting is a huge thing for modularity and extensibility, and people do frequently choose slow languages like Python for that. Then again, some languages (like some Python implementations) let you compile scripts on first run and execute binaries later on. I actually wish more languages were designed like Common Lisp is, where you keep a seamlessly integrated compiler available at runtime and are expected to take advantage of it - in case of SBCL (a CL implementation), this means a fast to-native compiler, which on occasions can make an application faster than it would be in an otherwise ahead-of-time compiled language.)

> Bigger - and slower - parts of the web app can be loaded after the app starts interacting. So - at least in principle - no sizeable speed difference, which would blow somebody away.

So can desktop apps. Except they rarely need that, if huge, because it's harder to make them slow by default.

I mean, take Slack - a frequent target of performance complaint. They have a bloated web client, an even worse Electron app, and here I am, using Ripcord[0] on both Windows and Linux (and it has a Mac version too), getting the same functionality at a fraction of the resource use, and there's literally nothing slow there. Nothing. Not a thing (except connecting) takes a perceptible delay. That's how fast you can make a modern chat client, if you care.

> Advantage of web app is cross platform uniformity. Write once, run everywhere.

That's a big advantage, true. It's easier. Though it does come at a cost.

--

[0] - https://cancel.fm/ripcord/


> Advantage of web app is cross platform uniformity. Write once, run everywhere.

In theory -- yes. But in practice, it is write once, debug anywhere. Remember a certain electron app consuming 100% CPU for a blinking cursor on a certain platform?


> In data centers, loading data from networked server, where it's in memory, can be used over loading data from a disk, because disk is comparatively slow.

RDMA has no relevance to this discussion.

> A web app can load JavaScript assembler, which isn't much slower than a desktop app written in C.

This is incredibly wrong. An Electron app goes through many stages before code is executing with acceptable performance:

1. A full web browser loads.

2. JavaScript is loaded and parsed.

3. JavaScript runs interpreted, which is very slow. It is only here that the "application" starts.

4. After a while, the JIT may decide to compile some code. This is very resource intensive.

5. After compilation, you finally have some parts that have decent performance. However...

6. Gaurds fail (i.e. bad assumptions), and the code is deoptimized, running at slow speed again. JIT compilations may be tried again later with new assumptions, and if you're lucky, they might hold.

At #5, you have code that is as fast as it gets. It is nowhere near as fast as native code (any benchmarks you think of are synthetic and designed to show JavaScript as fast—it doesn't take a lot to shake out the issues).

For a native application, however, the process looks like this:

1. The application starts, and it runs.

Done. There is no parsing, interpreting, optimization. This single step is orders of magnitude faster than just #1 of the life of an Electron app.

> Bigger - and slower - parts of the web app can be loaded after the app starts interacting. So - at least in principle - no sizeable speed difference, which would blow somebody away.

We are talking a speed difference in orders of magnitude here. An electron application is not even done preparing Electron before a good native application is done loading.

And it's all fine and dandy that you can load heavy things later, but for a good native application has nothing to load later. It's done.

A fun comparison:

1. Slack cold-start on my machine: ~3 seconds before anything shows up, ~5 seconds until a main window with a loading indicator is visible, ~10 seconds till fully loaded and usable.

2. Telegram-desktop cold start on my machine: ~1 second till fully loaded and usable.

And telegram-desktop is a very slow native application! A speedy application starts in 250ms or less, and never waits after that.

> Advantage of web app is cross platform uniformity.

And the disadvantage is that they are are huge, resource intensive and pathetically slow.

We have very functional cross-platform toolkits, like Qt that telegram is based on.


> At #5, you have code that is as fast as it gets. It is nowhere near as fast as native code (any benchmarks you think of are synthetic and designed to show JavaScript as fast—it doesn't take a lot to shake out the issues).

This. And to make matters worse, a lot of benchmarks start with something like, "To be fair to <the slower language>, let's cripple <the faster language> by implementing the programs using the paradigm favored by <the slower language>." If you want the real results, have an expert in each language implement the spec without looking at the other program.

Someone mentioned Photoshop being slow compared to Slack/VSCode. That is Apples to Oranges comparison if I ever saw one.

> And the disadvantage is that they are are huge, resource intensive and pathetically slow.

And don't work natively on any platform. You essentially program for the lowest common denominator and do not take advantage of any of the features provided by the platform -- especially accessibility. For example: Zoom In on any half-way decent editor increases the text size. Zoom In on VSCode (macOS) blows up the entire UI -- leaving little space for actual text. This is just one example -- I can line up many more.


Probably because your desktop apps are bloated, too. Any software that needs longer than zero point two seconds reacting to user action (this includes starting the program) should be improved upon.


I write moderately complex web apps and I have to say 200ms for a user interaction sounds like far too long. All apps regardless of where they're running should be managing a solid 60fps, which gives you a budget of 16ms for the UI to react to a user event.

Obviously starting the app is going to take longer, especially from cold, but if you ignore things like DNS resolution and download time then 200ms is more than enough for most things to get from 'downloaded' to 'interactive'.


It shouldn't be obvious that startup is slower and I didn't mean UI reaction, but the more broader reaction time. For example from typing a location and hitting enter, it should take something like Google Maps zero point two seconds at most to completely load the page and be done with everything. The user shouldn't have a concept of "loading time" and that includes starting the application.


It's funny you should mention google maps, as that's recently regressed to semi-unusable in firefox.


I think the only native apps that I use are Steam, Unity, Photoshop, SourceTree and VSCode. Out of those the only "fast" one is VSCode, which is actually written in JS. Even though you mentioned the browsers being "bloated", for me Chrome always starts up instantly and I have no responsivness issues when browsing sites, playing browser games or using browser apps.


Steam UI is also just a webview mosly. You can see its WebHelper processes. I would check if SourceTree is too.


Sourcetree is a native app.


Out of those the only "fast" one is VSCode, which is actually written in JS

Typescript I think? Anyway, much as Microsoft has done an amazing job with VS Code, it really doesn't have quite the snappy feel in all circumstances of a native app. Extension loading on start up is one example. If you use a keyboard mapping extension it's quite possible to start typing on launch and find the mapping hasn't kicked in yet.

That's not to say it isn't worth the tradeoff. The costs are inconsequential, and the benefits great. I'm mostly an IntelliJ Idea user, but the sheer speed with which VS Code is developed often tempts me towards it (eg. it's well ahead of Idea on wsl integration)


Do you really want to compare Photoshop with VSCode?


VSCode is anything, but "native".


I do like performant apps, but I've never understood the emphasis on startup time for most of them. There's the odd utility (eg. screenshotting) where an instant start is desirable. But the main things I use (terminal, editor/ide, browser etc) are started once per week at most.

I personally wouldn't want the developers of the software I depend on most to waste resources speeding up something of such marginal significance.

[Edit: an instant-start editor for config file, vim commit edits etc is of course crucial]


I have a workflow where I spawn and close terminals depending on whether I want something done. If my terminal startup wasn't instantaneous, I'd be switching to one that was. (Currently using urxvt). The only reason I keep my browser open is because it doesn't start instantaneously. Imagine a world where your computer and all your apps can start instantaneously. It would be viable to shutdown your computer when leaving the room instead of just locking it.

In this reality, however, I would already be happy if tabs in a browser could load that fast, so I wouldn't have to keep hundreds of them open all the time.


What desktop programs do you use that take fewer than 0.2 seconds to start?


fyi, I'm on Linux.

Here's a list: ranger, urxvt, sxiv, w3m, xev, vim, feh and qutebrowser.


vim is slow to start? Have you checked the SMART stats on your drive lately?


No, read the conversation again. I've listed stuff that loads faster than zero point two seconds.


This is what I do, ^E opens a vim buffer with the contents of whatever I’m editing.

Make my changes, save/quit and it appears in my text box in the browser. Obviously doesn’t work on my phone (why would I want it to?) but it’s a super nice workflow (if a bit jarring to have another program/terminal pop open).

I’m using qutebrowser for this, and this mechanism is an officially supported part of the browser.

https://www.reddit.com/r/qutebrowser/comments/780u6a/how_to_...


Qutebrowser is really amazing and I'm using it for lots of my browsing, too. What keeps me from going all in is the lack of something that can match ublock+umatrix. Sadly, the Internet has become a harsh place, where these things are needed.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: