Ditching Electron: How We Went from 170 MB to 3 MB Without Losing Our Minds

Imagine you want to build a desktop app using the same tools you'd use for a website — but without stuffing an entire web browser inside the box. This post is about how we did exactly that, and shrank our app from the size of a movie download to the size of a photo.


How We Went from 170 MB to 3 MB Without Losing Our Minds

Electron is the comfort food of desktop development. It's familiar, it works, and it gets you from zero to shipping fast. But at some point you look at your "Hello World with a sidebar" weighing 170 MB on disk, taking 3 seconds to cold-start, and eating 300 MB of RAM at idle — and you start asking uncomfortable questions.

We asked those questions. Then we replaced Electron with an embedded OS web view, a static JS build, and a thin layer of native helpers. The result: a 1–3 MB distributable, sub-second startup, and native-level memory usage. Here's the full story — the wins, the pain, and the trade-offs nobody warns you about.


The Architecture in a Nutshell

Instead of bundling an entire Chromium browser and Node.js runtime with every release, the new stack leans on what the operating system already provides:

macOSWKWebView (WebKit, ships with every Mac since 10.10). WindowsWebView2 (Chromium-based, ships with Windows 10/11 or installs as a ~1.5 MB evergreen runtime).


On top of the web view sits a static JS/HTML/CSS bundle — the same React (or Svelte, or vanilla) app you'd build anyway, just compiled with Vite or esbuild into a handful of small files.


For anything that needs OS-level access — file system, notifications, tray icons, auto-update, keychain, native menus — we wrote a thin native layer in Swift (macOS) and C++/Rust (Windows) that exposes a small JSON-RPC or postMessage bridge to the JS side.

That's it. No bundled browser. No bundled runtime. Just your code and a few native bindings.





The Cases: Why Teams Make This Move

Case 1: Distribution Size Matters More Than You Think

If your app targets enterprise environments behind slow VPNs, or emerging markets with metered connections, shipping 170 MB per update is a tax on every user. Delta updates help, but the baseline still matters. Going from 170 MB to 1–3 MB changes the math entirely — your app can auto-update silently in seconds, not minutes.


Case 2: Tray Apps and Lightweight Utilities

Not every desktop app is a full IDE. Status bar utilities, clipboard managers, quick-capture tools — these feel absurd at 170 MB. A web-view-based tray app can sit at 5–15 MB of RAM and launch in under 200 ms. It feels native because, resource-wise, it is native.


Case 3: Performance-Sensitive Workloads

Electron's multi-process architecture (main + renderer + GPU + utility) is powerful but heavy. If your app is doing real-time audio, managing local databases, or processing large files, every megabyte of overhead matters. A single web view process plus a lean native host gives you more headroom for the work that actually matters.


Case 4: Embedding Inside Another App

If you're building a plugin, extension, or embedded panel inside a larger native application, bringing Electron along is a non-starter. A web view component slots in naturally and shares the host process.


Case 5: You Already Have a Web App

If you have an existing, well-tested web frontend and you just need a desktop shell around it — deep links, offline support, system tray — the embedded web view approach gives you that wrapper without the Electron baggage.


The Positive Side

Dramatic Size Reduction

This is the headline number and it's real. A typical Electron app ships ~150–170 MB because it bundles Chromium (~120 MB) and Node.js (~30 MB). With an embedded web view, your distributable is literally just your app code plus a small native binary. For us, that meant going from 170 MB down to 1–3 MB depending on bundled assets.

Startup Time

Electron's cold start involves launching Chromium, initializing Node.js, and then loading your app. That's 2–4 seconds on average hardware. An OS web view is already a loaded system component — our cold start dropped to 200–400 ms. The app feels instant.

Memory Footprint

A minimal Electron app idles at 200–300 MB of RAM (Chromium is hungry). The same UI in a native web view idles at 30–80 MB. On machines with 8 GB of RAM, that difference is the gap between "one more app running" and "swap hell."

Native Feel

Because you're using actual OS components, you get native scrolling physics, native text rendering, native spell-check, and proper OS-level accessibility for free. No more fighting Electron's approximations.

Security Surface

Fewer bundled components means a smaller attack surface. You inherit the OS's web view security patches automatically — no waiting for Electron to rebase onto a newer Chromium. On macOS, WKWebView runs in a sandboxed process by default.

Simpler Updates

A 2 MB update downloads in seconds. You can ship multiple times a day without users even noticing. No more "a new update is available, restart to apply" friction.


The Negative Side

Browser Inconsistencies Are Back

With Electron, you target one browser engine (Chromium) and one version (the one you ship). With embedded web views, you're targeting WebKit on macOS and Chromium on Windows — two different engines with different quirks, different CSS support timelines, and different JavaScript engine behaviors. You're back to cross-browser testing, except the browsers are welded into the OS.


You Don't Control the Runtime Version

On macOS, WKWebView is tied to the macOS version. A user on macOS 12 gets a different WebKit than a user on macOS 14. You can't polyfill everything. On Windows, WebView2 is evergreen and auto-updates, which is better — but it's still not your version to pin. Features you rely on might behave differently across OS versions, and debugging "works on Ventura, breaks on Monterey" is not fun.


No Node.js

This is the big one. Electron gives you full Node.js access — fs, child_process, net, crypto, native modules via node-gyp, the entire npm ecosystem for backend logic. With a plain web view, you're in a browser sandbox. Every OS-level operation needs a native bridge: file access, networking beyond fetch, spawning processes, system integration. You have to build (or find) that bridge yourself.


The Native Layer Is Real Work

Writing and maintaining native code for two platforms is not trivial. Swift for macOS and C++/Rust for Windows means two codebases, two build systems, two sets of platform-specific bugs. If your team is pure JavaScript, this is a steep learning curve. Libraries like Tauri and Wry abstract some of this, but abstractions leak — eventually you'll be reading WinAPI docs at 2 AM.


DevTools Are Worse

Electron gives you full Chrome DevTools out of the box, including the network panel, performance profiler, and memory inspector. WebView2 on Windows can attach Edge DevTools, which is close. But WKWebView debugging requires Safari's Web Inspector, connecting via a separate app, and the experience is noticeably less polished. Console logging, remote debugging, and performance profiling all take more effort.


Ecosystem and Community

Electron has a massive ecosystem: electron-builder, electron-forge, electron-store, electron-updater, auto-update infrastructure, code signing helpers, crash reporters. The web view approach has a fraction of that. You'll either roll your own solutions or lean on younger projects like Tauri. Support forums are smaller, Stack Overflow answers are fewer, edge cases are less documented.


Accessibility Can Be Tricky

While native web views inherit OS accessibility features, the bridge between your JS app and native accessibility APIs can have gaps. Electron has years of work ensuring screen readers, keyboard navigation, and high-contrast modes work correctly across platforms. With a custom native layer, you may need to wire some of that up yourself.


Auto-Update Infrastructure

Electron has Squirrel, electron-updater, and built-in support for differential updates. With the web view approach, you need to build or integrate your own update mechanism — checking for versions, downloading the binary, verifying signatures, swapping the executable, and restarting gracefully. Sparkle works on macOS, WinSparkle on Windows, but it's two separate integrations.



Honest Comparison

Dimension

Electron

Embedded Web View

App size

150–170 MB

1–3 MB

Cold start

2–4 seconds

200–400 ms

Idle RAM

200–300 MB

30–80 MB

Browser consistency

One engine, one version

Two engines, OS-dependent versions

Node.js access

Full

None (bridge required)

DevTools

Chrome DevTools built in

Varies by platform

Native feel

Good with effort

Excellent by default

Ecosystem maturity

Very mature

Young but growing

Team skill requirement

JavaScript only

JavaScript + native (Swift/C++/Rust)

Update payload

50–170 MB

1–3 MB


When to Stay with Electron

Not every project should make this switch. Electron is still the right call when:

  • - Your team is JavaScript-only and the cost of hiring or learning native development is too high.

  • - You need deep Node.js integration — native modules, complex file system operations, or tight npm ecosystem coupling.

  • - Cross-browser consistency is critical and you can't afford to test against multiple web view versions.

  • - You need a battle-tested ecosystem for auto-updates, crash reporting, code signing, and CI/CD out of the box.

  • - Your app is complex enough that the 170 MB overhead is a rounding error compared to the value it delivers (think VS Code, Figma desktop, Slack).

When to Make the Switch

The embedded web view approach shines when:

  • - App size and startup speed are user-facing competitive advantages.

  • - Your app is a lightweight utility, tray app, or wrapper around an existing web app.

  • - You have native development capability on the team (or are willing to invest in it).

  • - You're targeting environments where bandwidth, disk space, or RAM are constrained.

  • - You want your desktop app to feel invisible — fast, light, and native.


Practical Starting Points

If you want to explore this approach without starting from scratch, a few tools can accelerate the path. Tauri is the most mature framework in this space — it provides the native shell, the JS bridge, and build tooling for both platforms. Wry is the underlying web view library Tauri uses, available as a standalone Rust crate if you want more control. On the Apple side, you can go fully native with a Swift + WKWebView setup in under 100 lines of code. On Windows, Microsoft's WebView2 SDK has solid documentation and C++/C# bindings.


Final Thought

Electron democratized desktop development, and that legacy is real. But the industry has moved. OS-level web views are now excellent, fast, and well-maintained. For many apps, the 170 MB Chromium tax is no longer a necessary cost of doing business.


Going from 170 MB to 3 MB isn't just a number on a spec sheet. It changes how users perceive your app — it downloads instantly, launches instantly, and sits quietly in the background. It changes how you ship — small, fast, fearless updates. And it changes how your app feels — less like a web page in a box, more like something that belongs on the machine.


The trade-off is real: you lose Electron's convenience and ecosystem in exchange for size, speed, and nativeness. Whether that trade-off is worth it depends entirely on what you're building and who you're building it for.


For us, it was worth every line of native code.