When we talk about a “desktop application,” we generally mean a program that runs with a graphical UI that’s native to the platform or powered by some cross-platform visual toolkit. But a desktop application these days is just as likely to be a glorified web page running in a standalone instance of a browser.
If that sounds like a criticism, it isn’t. The web UI desktop app makes it possible to deliver rich UIs using the entire existing culture of user interface components created for the web. Still, that power and flexibility come at a cost—enough so that the effort of developing a native desktop application may be worth it.
What exactly is a native desktop app?
What are we calling a “native” desktop application, anyway?
Mostly, this comes down to the difference between a program that uses web technology—a web UI, packaged in an instance of a web browser—versus a program that uses the platform’s own GUI system, or a third-party, cross-platform GUI that isn’t primarily web-based.
Desktop applications like Visual Studio Code or the Slack client are web-based. They build atop technologies like Electron or Tauri, where your app’s front end is built with HTML, CSS, and JavaScript. (The back end can also be JavaScript but it’s not required.)
True desktop applications like the full-blown Visual Studio product, Microsoft Word, or the Adobe Creative Suite don’t use a web-based front end or packaging. Some of that is the weight of a legacy codebase, created before web UI apps and Electron: if it isn’t broken, don’t change it. But native apps also provide much finer control over the user experience, at the cost of requiring more development.
Benefits of web-based apps
The biggest advantage of a web UI app over a native desktop app is its ability to leverage the massive ecosystem of web-based UI components. If there’s some UI element you want to present to the user, odds are a web version of it exists. Not only that, but it will often be far easier to implement than a platform-native version would be.
Because web components are so universal, it’s far easier to repurpose one for a web UI app than to use a widget written for some other toolkit or windowing system. This doesn’t just include common components like forms and input fields, but more complex interfaces like interactive 3D charts. Most everything that can be part of a native app’s UI can be delivered as a web component of some kind.
Web UI apps also offer portability. It’s far easier to deliver a cross-platform version of a web UI app than its native counterpart. Just about all the abstractions for the platform, such as how to deal with the clipboard, are handled by the browser runtime.
Downsides of web UIs for desktop apps
All the above advantages for web UIs come with drawbacks. The single biggest one is dependency on the web browser—whether it’s one bundled with the application or a native web view on the target platform.
Bundling a browser with the application is the most common approach; it’s what Electron and its spin-offs do. This gives developers fine-grained control over which edition of the browser is used, what requirements it supports, and how it supports them. But that control comes with a massive downside in the size of the binary artifact. Browser bundles can reach 100MB or so for even a simple “hello world” application.
One possible way around this is to just invoke whatever native web view is available on the target platform. That cuts down drastically on the size of the deliverable, but you don’t always know what the web view’s baseline capabilities will be.
If you aren’t using bleeding-edge browser features, you can typically get away with using the web view. But if you do anything involving, say, WebAssembly or other rapidly developing browser technologies, it’s safe to assume a platform web view will lag behind current browser editions by at least a year.
Another significant limitation is that any interaction between the app’s UI and its back end are limited to what can be supported by the browser. Most of the time, this means you’ll have to confine those interactions to what can go through a local network socket between the browser and the back end. In theory, it could include a browser plugin or “component extension” (via Chrome), but most web UIs will use a network connection.
One major way this can manifest is in UI latency. Real-time updates streamed to the browser from a back end will be bottlenecked by the network stack. The most performance-intensive work could be moved into the browser—for instance, as a WebAssembly module—but at the potential cost of adding another language or set of build steps to the project’s requirements.
How to choose between a native app or web UI
A completely native app—one that runs without the need for a web UI—is likely your best choice when you have the following criteria:
- A web UI isn’t vital. For example, a lightweight command-line tool could have an optional web interface for convenience but doesn’t need it to function.
- The size of the deliverable matters. (The command-line tool example also fits here.)
- You want as few layers as possible between the app and the operating system or the underlying system.
- The UI needs minimal latency, or the most performance-sensitive code can’t run in the browser.
A web UI makes most sense when:
- The size of the deliverable is negotiable.
- The ease of using web components for the front end is essential to the app’s ongoing development.
- It is acceptable to work with the underlying system through the abstractions provided by the browser.
- The front end doesn’t need to have the lowest possible latency with the back end. (Or when any performance-sensitive behavior can be moved into the browser.)
The line between local apps and web apps is blurring, and it has been for some time. The web has become its own application platform, offering conveniences that conventional desktop apps struggle to match. But the desktop, and the command line along with it, have not vanished, and for good reason.