Salta al contenuto principale

01 - Tauri 2 vs Electron: 90% bundle reduction

Tauri 2 o Electron: che cosa pesa in un'app desktop, una misura che puoi rifare, quando il vantaggio si riduce e il prezzo delle WebView di sistema.

Cosa ne pensi di questo articolo?

01 - Tauri 2 vs Electron: 90% bundle reduction
Tauri Rust DesktopFoto:Daniil KomovPexels

In Breve

Tauri 2 o Electron: che cosa pesa in un'app desktop, una misura che puoi rifare, quando il vantaggio si riduce e il prezzo delle WebView di sistema.

Quanto pesa davvero un'app desktop web, e perché la risposta cambia

Se devi consegnare un'app desktop costruita con tecnologie web, la scelta fra Tauri 2 ed Electron parte quasi sempre dal peso del download. La risposta breve è che la differenza esiste ed è grande, perché Electron porta con sé un browser intero (Chromium) e Node.js, mentre Tauri usa la WebView che il sistema operativo ha già. Ma una percentuale fissa come «-90%» non regge: dipende dal formato in cui consegni l'app (installer, AppImage, installazione offline) e da quanto lavori sul profilo di compilazione. Qui trovi una misura che puoi rifare, i casi in cui il vantaggio si assottiglia e il prezzo che paghi in cambio, cioè una WebView diversa su ogni piattaforma.

Una precisazione su che cosa ho potuto provare. Sulla macchina su cui ho scritto non ci sono Rust né Cargo, quindi non ho compilato nessuna app Tauri e non ho misurato installer di Tauri: le dimensioni di Tauri che leggi sono quelle dichiarate dalla documentazione ufficiale, citate come tali. Ho eseguito lo script Python della prossima sezione, ho validato tauri.conf.json contro lo schema ufficiale e ho letto la documentazione di Tauri 2 il 2026-11-13. Gli altri listati sono schemi da adattare al tuo progetto. Questo è il primo articolo della serie e non richiede prerequisiti, se non sapere che cosa sono un bundle JavaScript e un installer.

Che cosa c'è dentro un'app Electron, con numeri che puoi rifare

La documentazione di Electron lo dice in una riga: il framework funziona «embedding Chromium and Node.js into its binary». Quindi il peso di partenza di qualunque app Electron è quello del runtime, prima ancora del tuo codice. Per misurarlo senza scaricare un centinaio di megabyte basta chiedere a GitHub le dimensioni degli asset di una release: ogni asset ha un campo size in byte.

Dimensione del runtime Electron, da una release pubblicata
import json
import urllib.request

TAG = "v45.3.1"
URL = f"https://api.github.com/repos/electron/electron/releases/tags/{TAG}"
WANTED = [
    f"electron-{TAG}-linux-x64.zip",
    f"electron-{TAG}-darwin-arm64.zip",
    f"electron-{TAG}-win32-x64.zip",
]

request = urllib.request.Request(URL, headers={"User-Agent": "misura-dimensioni"})
with urllib.request.urlopen(request, timeout=30) as response:
    release = json.load(response)

sizes = {asset["name"]: asset["size"] for asset in release["assets"]}
for name in WANTED:
    megabytes = sizes[name] / 1_000_000
    print(f"{name}: {sizes[name]} byte = {megabytes:.1f} MB")

# Output (v45.3.1, due esecuzioni identiche):
# electron-v45.3.1-linux-x64.zip: 123927956 byte = 123.9 MB
# electron-v45.3.1-darwin-arm64.zip: 121031836 byte = 121.0 MB
# electron-v45.3.1-win32-x64.zip: 158352921 byte = 158.4 MB

Lo script legge la release con il tag fissato v45.3.1 e non releases/latest: con «latest» l'uscita cambierebbe a ogni nuova versione e non potresti confrontare due esecuzioni. L'intestazione User-Agent serve perché l'API di GitHub rifiuta le richieste che non ne hanno uno. Il risultato è identico in due esecuzioni consecutive, consultato il 2026-11-13: da circa 121 MB (macOS Apple Silicon) a circa 158 MB (Windows x64), contando 1 MB come un milione di byte.

Leggi il numero con tre cautele. Sono archivi zip del runtime nudo, senza la tua app e senza l'installer che l'utente scarica davvero. Sono compressi, quindi lo spazio occupato sul disco dopo l'installazione è maggiore. E non dicono nulla su un'app finita, che dipende dallo strumento con cui impacchetti. Se qualcuno ti mostra «Electron 150 MB contro Tauri 10 MB» senza dire quale file ha pesato, sta confrontando formati diversi.

Che cosa c'è dentro un'app Tauri

L'architettura è descritta nella pagina «Process Model» della documentazione: ogni app ha un core process scritto in Rust, che è l'unico componente con accesso pieno al sistema operativo, e che avvia una o più finestre WebView. La libreria di WebView non è dentro il tuo eseguibile: è collegata dinamicamente a runtime. La pagina introduttiva ne trae la conseguenza che un'app Tauri minima può restare sotto i 600 KB. Quel numero descrive un'app piccola con pochi asset, non la tua.

Ecco il punto che i confronti saltano: il tuo frontend pesa quanto pesa, con Tauri come con Electron. Supponi, solo per ragionare e non come misura, un frontend Angular compilato da 3 MB. Quei 3 MB li porti in entrambi i casi, quello che cambia è tutto il resto. La differenza fra i due framework sta quindi nel runtime, cioè nei circa 120-160 MB misurati sopra contro la parte Rust del core, e non nell'interfaccia.

La parte Rust la controlli tu, e la leva più semplice è il profilo di rilascio in Cargo.toml. La pagina «App Size» della documentazione propone questa configurazione per la toolchain stabile.

Profilo di rilascio orientato alla dimensione
[profile.dev]
incremental = true

[profile.release]
codegen-units = 1  # lascia a LLVM più margine di ottimizzazione
lto = true         # ottimizza anche attraverso i confini fra crate
opt-level = "s"    # privilegia la dimensione; con 3 si privilegia la velocità
panic = "abort"    # niente tabelle di unwinding
strip = true       # toglie i simboli di debug dal binario

Riga per riga. opt-level = "s" chiede al compilatore di ottimizzare per la dimensione; con 3 ottimizzi la velocità, e la documentazione di Cargo avverte che i livelli "s" e "z" non producono sempre binari più piccoli, quindi la prova è misurare. lto = true abilita le ottimizzazioni sull'intero grafo delle dipendenze, al prezzo di un collegamento più lungo. codegen-units = 1 impedisce di spezzare il crate in più unità: sono più lente da compilare ma ottimizzate meglio. strip = true toglie i simboli di debug, e quindi anche la possibilità di leggere un crash report con nomi di funzione.

panic = "abort" è la riga che richiede una decisione. Con questa impostazione un panic termina il processo invece di srotolare lo stack, e il codice che conta su catch_unwind per sopravvivere a un panic smette di funzionare. In un'app desktop il caso tipico è un thread che va in panic: con abort si chiude tutta l'app. Se preferisci una chiusura meno brutale, lascia il valore predefinito e accetta un binario un po' più grande, di cui puoi misurare lo scarto con i comandi dell'ultima sezione.

Togliere i comandi che non usi

Una seconda leva è nella configurazione. Dalle versioni tauri 2.4 e tauri-cli 2.4 esiste l'opzione build.removeUnusedCommands, che elimina dal binario i comandi che nessun file di capability autorizza. Il file seguente è un tauri.conf.json completo per un frontend che gira in sviluppo su localhost:4200, come il server di sviluppo di Angular.

tauri.conf.json con removeUnusedCommands
{
  "$schema": "https://schema.tauri.app/config/2",
  "productName": "Appunti",
  "version": "0.1.0",
  "identifier": "dev.example.appunti",
  "build": {
    "devUrl": "http://localhost:4200",
    "beforeDevCommand": "npm start",
    "beforeBuildCommand": "npm run build",
    "frontendDist": "../dist",
    "removeUnusedCommands": true
  },
  "app": {
    "windows": [{ "title": "Appunti", "width": 900, "height": 640 }],
    "security": { "capabilities": ["main-capability"] }
  },
  "bundle": { "active": true, "targets": "all" }
}

Le chiavi devUrl e beforeDevCommand dicono a Tauri dove trovare il server di sviluppo e come avviarlo; frontendDist è la cartella statica che finisce nell'app in produzione; identifier è l'identificativo univoco dell'app, usato anche dalle firme. Ho validato questo file contro lo schema JSON ufficiale (versione 2.12.5, scaricato da schema.tauri.app) con un validatore: risulta valido, mentre una copia con la chiave scritta male (removeUnusedCommandz) viene rifiutata come proprietà non ammessa.

L'opzione ha due limiti scritti nella documentazione. Il beneficio si vede solo se nei file di capability elenchi i singoli comandi invece di usare i permessi default, che ne abilitano molti. E non considera le ACL aggiunte a runtime, quindi se le usi devi verificare a mano che il comando che ti serve non sia stato tolto.

Dove il confronto di peso diventa meno favorevole

Tre casi riducono il vantaggio, e tutti sono documentati. Il primo è la consegna come AppImage su Linux: la pagina dedicata avverte che il file cresce «from the 2-6 MB range to 70+ MB», perché l'AppImage porta con sé le dipendenze. Il secondo è Windows: se l'utente non ha già WebView2, l'installer deve procurarselo, e come lo fa cambia il peso.

Modalità WebView2Serve rete?Peso aggiunto all'installer
downloadBootstrapper (predefinita)Sì0 MB
embedBootstrapperSìcirca 1,8 MB
offlineInstallerNocirca 127 MB
fixedVersionNocirca 180 MB

La tabella (dalla pagina «Windows Installer») mostra il compromesso: l'installer piccolo presuppone una connessione, quello per ambienti offline incorpora un runtime che pesa quanto un intero Electron, circa 127 MB contro i 121-158 MB misurati sopra. Su Windows 10 dalla versione 1803 e su Windows 11 WebView2 è già nel sistema, quindi per la maggior parte degli utenti vale la riga a 0 MB. Il terzo caso sei tu: un'app con molte dipendenze Rust, o con asset pesanti, cresce a prescindere dal framework.

Il prezzo: una WebView diversa su ogni piattaforma

Non portare Chromium significa non decidere quale motore esegue la tua interfaccia. Su Windows Tauri usa WebView2, basata su Chromium e capace di aggiornarsi da sola. Su macOS usa WKWebView, parte del sistema e aggiornata con il sistema: le versioni di macOS non più supportate non ricevono aggiornamenti di WebKit. Su Linux usa webkit2gtk, e la versione dipende dalla distribuzione; la pagina «Webview Versions» dichiara che la propria tabella delle distribuzioni è molto incompleta. Con Electron, invece, il motore è quello che hai impacchettato: lo scegli tu e lo aggiorni tu a ogni release, il che toglie variabilità e ti lascia la responsabilità delle patch di sicurezza di Chromium.

In pratica la verifica che cambia è questa. Per ogni funzione CSS o API JavaScript che usi, controlla il supporto non solo in Chrome ma anche nel Safari corrispondente al WebKit del tuo macOS minimo e nella WebKitGTK della distribuzione Linux più vecchia che vuoi supportare. La documentazione di Tauri 2 indica Ubuntu 22.04 e Debian 12 come base di compilazione adatta, perché richiede WebKitGTK 4.1. Se un utente apre l'app e un elemento non si dispone come sul tuo portatile, la causa più probabile è il motore, non il tuo codice.

Sicurezza: le capability prendono il posto dell'allowlist

Il frontend gira nella WebView e può chiamare il core Rust solo tramite messaggi. In Tauri 1 i permessi stavano in una sezione allowlist di tauri.conf.json; la guida di migrazione dice che in Tauri 2 è stata rimossa e sostituita dal sistema di permessi e capability. Una capability è un file in src-tauri/capabilities che assegna permessi a finestre precise.

Capability della finestra principale
{
  "identifier": "main-capability",
  "description": "Permessi della finestra principale",
  "windows": ["main"],
  "permissions": [
    "core:window:default",
    "core:window:allow-set-title",
    "store:default"
  ]
}

Il file concede alla finestra con etichetta main i permessi di base sulle finestre, la modifica del titolo e le operazioni predefinite del plugin store (che va installato a parte). Le etichette contano, non i titoli: la documentazione ricorda che i confini di sicurezza si basano sulle etichette delle finestre. Elencare main-capability in app.security.capabilities, come nel file di configurazione sopra, restringe l'app a quelle sole capability: senza elenco sono attive tutte le capability presenti nella cartella.

Un dettaglio da non perdere: i comandi che registri tu con invoke_handler sono, per impostazione predefinita, invocabili da tutte le finestre dell'app. Per restringerli devi elencarli in AppManifest::commands nello script build.rs. Inoltre la documentazione elenca ciò da cui le capability non proteggono: codice Rust insicuro, scope troppo larghi, vulnerabilità nella WebView di sistema, compromissione della catena di fornitura.

Se il tuo frontend è Angular

La pagina «Frontend Configuration» spiega che Tauri si comporta come un host di file statici: gli chiedi di servire una cartella di HTML, CSS e JavaScript, quindi vanno bene generazione statica, applicazioni a pagina singola o multipagina, e non è supportato il rendering lato server. Angular non compare fra i framework con una guida dedicata (ci sono Next.js, Nuxt, Qwik, SvelteKit, Vite, Leptos e Trunk), ma la stessa pagina dice che un framework non elencato può funzionare senza configurazione aggiuntiva.

Un'applicazione Angular compilata come SPA statica rientra in questo schema; un'applicazione che dipende dall'SSR, come questo sito, no. Non ho provato Angular dentro Tauri: è un'indicazione ricavata dalla documentazione, da verificare con un progetto di prova prima di pianificare una migrazione.

Come scegliere, con i compromessi

I criteri che spostano davvero la decisione sono pochi, e qui sono elencati senza una gerarchia fissa:

  • Backend già scritto in Node: Electron incorpora Node.js, quindi il codice JavaScript del backend si riusa; in Tauri la logica nativa è Rust e i processi esterni passano dal plugin shell.
  • Team senza esperienza di Rust: Tauri ha una curva d'ingresso reale, perché ogni funzione nativa è codice Rust.
  • Rendering identico ovunque: con Electron il motore è sempre il tuo Chromium; con Tauri è quello del sistema.
  • Download e spazio come vincolo: qui Tauri vince nettamente, entro i limiti della sezione precedente.
  • App mobile dallo stesso progetto: Tauri 2 prevede Android e iOS, Electron è per Windows, macOS e Linux.

Nessun criterio decide da solo. Se il tuo problema è il peso, ma il team scrive Node da anni e il backend è già in JavaScript, il risparmio può non ripagare la riscrittura. Se invece nessuno dipende da Node e la banda dei tuoi utenti è il vero collo di bottiglia, lo stesso risparmio pesa più di tutto il resto. Per la maturità conta anche la data: Tauri 2.0 è stato annunciato stabile il 2 ottobre 2024, e al 2026-11-13 la versione stabile del crate è la 2.12.5, mentre la serie 3 è ancora in alpha.

Come misurare la tua app prima di decidere

Il confronto che serve a te non è fra due medie, è fra due build della tua app. Se hai un prototipo, compila e guarda cosa produce il bundler.

Misura dei bundle prodotti da una build Tauri
# dalla radice del progetto, dopo aver installato i prerequisiti di Tauri
npm run tauri build
du -sh src-tauri/target/release/bundle/*
ls -l src-tauri/target/release/appunti

Schema da adattare, non eseguito qui: il nome del binario (appunti) segue il productName del tuo progetto. du -sh riporta la dimensione di ogni formato prodotto nella cartella bundle, mentre ls -l sul binario ti dà il peso dell'eseguibile da solo. Confronta formati equivalenti (installer con installer, sulla stessa macchina) e riporta sempre il formato accanto al numero: è l'unico modo per evitare un confronto che non regge.

Domande frequenti

Il «90% di bundle in meno» è un numero reale?

Non come valore fisso. Il runtime di Electron misura circa 121-158 MB compresso, e un'app Tauri minima può restare sotto i 600 KB secondo la documentazione, ma il rapporto fra due runtime non è il rapporto fra due installer. Dipende da formato di consegna, dipendenze Rust e asset, e la misura valida è quella fatta sulla tua app.

Posso usare Angular, React o Vue con Tauri?

Sì, purché il frontend si compili in file statici: Tauri non supporta il rendering lato server. React, Vue e Svelte rientrano nella guida per Vite, che la documentazione raccomanda per le SPA; Angular non ha una guida ufficiale e segue la checklist generale.

Tauri funziona anche su Android e iOS?

Sì, dalla versione 2.0 stabile del 2 ottobre 2024. Che cosa funzioni e che cosa no, plugin per plugin, lo trovi in Tauri mobile su Android e iOS: stato del supporto.

Come distribuisco gli aggiornamenti di un'app Tauri?

Con il plugin ufficiale updater, che richiede una coppia di chiavi dedicata e non è disponibile su mobile. La procedura, insieme alla firma del codice, è in Distribuzione su macOS, Windows e Linux.

Che cosa sai fare adesso

Sai che cosa pesa in un'app Electron e perché, e come rifare la misura dalle release pubblicate. Sai leggere un'affermazione come «-90%» chiedendoti quale formato è stato pesato, e conosci i tre casi in cui il vantaggio di Tauri si riduce. Sai che la WebView di sistema è il prezzo da pagare e dove si vede, come restringere i permessi con le capability, e quale configurazione di Cargo e di tauri.conf.json prova a ridurre il binario. Il passo successivo è la comunicazione fra Rust e frontend, nell'articolo Tipi condivisi fra Rust e TypeScript; per l'ecosistema di estensioni vai a I plugin di Tauri 2.

Fonti

  • Tauri 2: What is Tauri? - il limite dichiarato di 600 KB per un'app minima e l'uso della WebView di sistema, consultata il 2026-11-13
  • Tauri 2: Process Model - core process, WebView collegate dinamicamente, principio del minimo privilegio, consultata il 2026-11-13
  • Tauri 2: App Size - profilo Cargo e opzione removeUnusedCommands con i requisiti di versione, consultata il 2026-11-13
  • The Cargo Book: Profiles - significato di opt-level, lto, codegen-units, panic e strip, consultata il 2026-11-13
  • Tauri 2: Webview Versions - WebView2, WKWebView e webkit2gtk, aggiornamenti e incompletezza della tabella Linux, consultata il 2026-11-13
  • Tauri 2: Windows Installer - le modalità di installazione di WebView2 e il peso aggiunto, consultata il 2026-11-13
  • Tauri 2: AppImage - crescita da 2-6 MB a oltre 70 MB e base di compilazione consigliata, consultata il 2026-11-13
  • Tauri 2: Capabilities - struttura del file, permessi per finestra, comandi di default e limiti della protezione, consultata il 2026-11-13
  • Tauri 2: Frontend Configuration - Tauri come host statico, assenza di supporto per l'SSR, elenco dei framework documentati, consultata il 2026-11-13
  • Tauri 2.0 Stable Release - data del rilascio stabile (2 ottobre 2024) e supporto mobile, consultata il 2026-11-13
  • Tauri 2: Upgrade from Tauri 1 - la rimozione di tauri.allowlist in favore dei permessi, consultata il 2026-11-13
  • crates.io: tauri - versione stabile 2.12.5 e serie 3.0.0 in alpha, letti dall'API del registro il 2026-11-13
  • Electron: Introduction - Chromium e Node.js incorporati nel binario, consultata il 2026-11-13
  • GitHub REST API: Releases - l'elenco degli asset di una release con il campo size usato dallo script, consultata il 2026-11-13

Lo script Python è stato eseguito due volte con la stessa uscita; tauri.conf.json è stato validato contro lo schema JSON di Tauri 2.12.5 e il profilo Cargo è stato letto come TOML. Il resto dei listati è uno schema da adattare, non compilato: sulla macchina di scrittura non ci sono Rust né Cargo.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti