Chaque année, le même schéma se rejoue. Une équipe a besoin d’une app desktop. Elle attrape Electron parce que tout le monde attrape Electron. Un mois plus tard, elle livre une binary de 180 Mo qui avale 400 Mo de RAM pour afficher un formulaire et trois onglets, et se demande pourquoi l’app ne se sent pas comme une app Mac sur un Mac.
Electron est un défaut. Ce n’est pas toujours le bon choix.
La réponse courte. Flutter est une option mature pour le développement d’apps desktop cross-platform. Il ship une binary de base d’environ 30 Mo, rend sa propre UI via Skia ou Impeller à 60 à 120 fps, tourne sur Windows, macOS et Linux, et partage du code avec iOS, Android et le web depuis la même base de code Dart. Si vous utilisez déjà Flutter en mobile, le desktop est l’extension peu chère. Si vous avez une app Electron qui tourne, restez tant que vous n’avez pas de vraie raison de migrer.
Qu’est-ce que le développement d’apps desktop cross-platform ?
Le développement d’apps desktop cross-platform consiste à construire une base de code unique qui tourne sur Windows, macOS et Linux, au lieu de maintenir trois projets natifs. Les quatre options que la plupart des équipes évaluent aujourd’hui :
- Electron (Node et Chromium). Écosystème dominant, plus grosse communauté, plus grosses binaries.
- Flutter (Dart avec Skia ou Impeller). Une base de code pour mobile, web et desktop.
- Tauri (backend Rust, webview système en frontend). Binary réduite, écosystème plus jeune.
- Qt ou natif (C++, Swift, WinUI). Fidélité maximale, coût maximal.
Chacun arbitre différemment taille de binary, mémoire, feel, developer experience, et à quel point le résultat paraît natif à la personne qui s’en sert réellement.
Pourquoi Flutter pour le desktop (et pourquoi pas)
Flutter est passé en stable sur Windows en 2022 et sur macOS et Linux dans la même fenêtre. Ce n’est plus expérimental.
Nous avons livré nous-mêmes des apps Flutter desktop, dont un outil de surveillance d’examens pour la haute école Karel de Grote qui capture les paquets réseau, détecte les machines virtuelles et énumère les adaptateurs matériels sur Windows, macOS et Linux depuis une seule base de code Flutter. Notre insight Flutter FFI explique comment cette intégration native fonctionne concrètement.
Ce que Flutter desktop fait bien :
Une base de code, tous les écrans. Une app Flutter bien architecturée tourne sur iOS, Android, Windows, macOS, Linux et le web depuis les mêmes widgets. Le code spécifique à la plateforme (menus, gestion des fenêtres, raccourcis) vit dans de fines couches conditionnelles. Pour une équipe qui livre déjà Flutter mobile, ajouter le desktop est une affaire de semaines, pas de mois.
Taille et mémoire. L’écart entre Flutter et Electron n’est pas théorique. Il se voit sur disque, en RAM et dans le pipeline de rendu.
Cet écart compte pour les équipes IT qui déploient sur des flottes Windows verrouillées et pour les utilisateurs sur du matériel plus ancien. 170 Mo d’écart en taille de binary, c’est la différence entre « approuvé rapidement » et « refusé par la politique » dans beaucoup d’environnements d’entreprise.
L’écart de Flutter face au natif est d’environ 2x sur la binary et la RAM. Face à Electron, il est plus proche de 5x. Et là où ce 2x face au natif fait vraiment mal (une boucle de rendu, un pipeline audio, un étage de compression), dart:ffi vous laisse descendre vers du C ou du Rust pour ce seul hot path et garder tout le reste en Flutter. L’histoire du partage de code cross-platform reste intacte.
Le feel. Flutter rend sa propre UI à 60 à 120 fps via Skia ou Impeller. Scroll, animation et latence d’input paraissent natifs sur du matériel courant. Il faut encore respecter les conventions de plateforme (menus sur macOS, clic droit sur Windows, raccourcis Ctrl vs Cmd) mais la couche widgets est assez rapide pour que rien ne donne l’impression d’une page web dans une fenêtre.
Natif quand il faut, Flutter partout ailleurs. « Cross-platform » en Flutter ne veut pas dire « full Dart ». Les hot paths critiques en performance ne vous forcent pas à quitter le framework. Vous descendez vers du C ou du Rust via dart:ffi pour les parties qui demandent une vraie vitesse native (pipelines d’images, DSP audio, capture de paquets, cryptographie, énumération matérielle) et vous gardez Flutter pour tout autour : UI, état, navigation et orchestration cross-platform. L’outil de surveillance d’examens KDG mentionné plus haut est exactement ce pattern, avec un shell Dart et un hot path en C. Les deux sortent de la même commande flutter build. Les platform channels (pour appeler Swift, Objective-C, Kotlin ou C++) couvrent les APIs OS de plus haut niveau là où FFI est excessif.
À quoi ressemble vraiment une base de code unique. Le hello-world pour Flutter desktop est identique à celui pour Flutter mobile :
import 'package:flutter/material.dart';
void main() => runApp(
const MaterialApp(
home: Scaffold(
body: Center(child: Text('Hello, Desktop')),
),
),
);
Lancez-le avec flutter run -d macos, flutter run -d windows ou flutter run -d linux. C’est tout le point d’entrée. Le code spécifique à la plateforme vient ensuite, dans de fines couches conditionnelles pour les menus, les raccourcis et la gestion des fenêtres.
Ce que Flutter desktop ne fait pas bien :
Tous les packages ne sont pas prêts pour le desktop. pub.dev contient des milliers de packages qui ciblent le mobile et ne font rien (ou crashent) silencieusement sur le desktop. Vous passerez du temps à vérifier le support plateforme de chaque dépendance.
L’accessibilité traîne par rapport au natif sur Windows et Linux. Le support lecteur d’écran sur Windows et Linux est plus faible que sur iOS, Android et macOS. Pour des applications accessibility-first, testez cela avant de vous engager.
Saisie texte et IME. Les méthodes d’entrée asiatiques et certains claviers internationaux ont encore des aspérités. Testez avec les locales que vos utilisateurs tapent réellement.
Les charges graphiques et latence-sensibles demandent un hybride. CAO, stations audio numériques, éditeurs vidéo temps réel et moteurs de jeu ont des plafonds de performance qu’un pipeline 100% Dart n’atteindra pas. Flutter n’est pas un moteur de jeu et n’essaie pas de l’être. Mais vous n’avez pas à abandonner Flutter pour ces apps non plus : le shell, l’UI, l’état et l’orchestration cross-platform restent en Dart, et la boucle de rendu, la chaîne DSP ou le pipeline d’encodage descendent vers du C ou du Rust via dart:ffi. Même flutter build, même histoire cross-platform, performance native là où ça compte.
Quand Flutter est le bon choix pour votre app desktop
Pour tout ce qui tient de la productivité, des opérations, de l’admin, du creative tooling et du SaaS vertical, Flutter desktop est le défaut pragmatique pour les nouveaux projets.
Les choses desktop-spécifiques que vous câblerez vraiment
Une vraie app Flutter desktop finit par écrire une poignée de choses qu’une app Flutter mobile n’a pas besoin d’écrire :
Gestion des fenêtres. Multi-fenêtres, dimensionnement et persistance de l’état des fenêtres passent par des packages comme window_manager ou bitsdojo_window. Les deux sont matures.
Menu bar et raccourcis clavier. Les menus natifs utilisent le PlatformMenuBar intégré à Flutter sur macOS et des APIs équivalentes sur Windows et Linux. Au niveau widget, Shortcuts et Actions rendent les raccourcis composables d’une plateforme à l’autre.
File picker et drag and drop. file_picker et desktop_drop couvrent les cas courants. Les permissions sandbox sur macOS demandent de l’attention.
Intégration native via dart:ffi. Pour des APIs OS sans package Dart, vous écrivez quelques lignes de C ou de Rust et les exposez via dart:ffi. C’est la voie que nous prenons quand il nous faut une capacité pas encore empaquetée.
Packaging et distribution. Windows utilise MSIX ou Inno Setup. macOS utilise DMG avec notarization. Linux utilise snap, flatpak ou deb. L’auto-update passe par le package auto_updater ou une implémentation custom autour de votre propre serveur de mise à jour.
Signature de code et notarization. Toute app desktop en production a besoin des deux. Prévoyez une journée pour la première notarization Apple, moins pour la seconde.
La question de la migration depuis Electron
Les équipes qui font tourner Electron nous demandent si elles devraient migrer vers Flutter. La réponse honnête : cela dépend des déclencheurs que vous rencontrez. Le coût de migration est réel et la plupart des apps Electron qui tournent n’ont pas besoin de bouger en urgence. Mais pour les équipes qui cochent l’un des signaux ci-dessous, l’équation s’inverse et le coût de rester devient plus élevé que le coût de bouger.
- La mémoire ou la taille de binary est devenue un bloqueur de déploiement. Politiques de flotte Windows, plaintes clients sur la RAM, déploiements terrain sur du vieux matériel. Si l’empreinte vous coûte des deals ou génère des tickets de support, c’est un déclencheur.
- Vous prévoyez une version Flutter mobile ou web du même produit. Dès que le partage de code cross-platform est sur la roadmap, chaque mois passé à maintenir deux stacks est un coût que vous n’avez pas à porter.
- Vous avez mesuré un écart de performance ou de feel qu’Electron ne peut pas combler. Pas une intuition. Latence d’input, fluidité d’animation, temps de démarrage, mesurés contre la baseline native que vos utilisateurs attendent.
- Votre équipe passe des sprints à maintenir Electron en vie. Montées de version Chromium, cycles de patch sécurité, churn des dépendances. Si la maintenance mange le travail de feature, ça compte aussi.
Si un ou plusieurs de ces signaux vous concernent, les questions suivantes portent sur la quantité d’app existante réutilisable, les morceaux spécifiques à la plateforme à reconstruire et la timeline réaliste. C’est une conversation, pas une formule, et c’est la même que nous avons avec les équipes qui envisagent une migration React Native vers Flutter. Notre service de migration legacy couvre le parcours complet de discovery et de livraison pour les équipes qui ont décidé que l’heure est venue.
À retenir
Electron est un défaut, pas une décision. La plupart des équipes l’attrapent parce que tout le monde le fait. C’est correct quand c’est la bonne réponse. Ce n’est souvent pas le cas.
Flutter desktop est prêt pour la production aujourd’hui. Windows, macOS et Linux, avec des déploiements phares chez Canonical et des vraies apps dans des agences comme la nôtre. La plateforme a dépassé l’étiquette « expérimental ».
Le plus gros levier est le partage de code. Si vous livrez déjà une app Flutter mobile, ajouter le desktop prend quelques semaines. Si vous livrez le desktop d’abord, ajouter mobile et web plus tard est tout aussi peu cher. Electron ne vous donne que le desktop.
Migrez sur déclencheurs, pas par principe. Les apps Electron qui tournent n’ont pas besoin de bouger en urgence. Quand mémoire, taille de binary, feel, charge de maintenance ou partage de code cross-platform deviennent un bloqueur réel sur lequel vous pouvez pointer du doigt, il est temps d’en parler.
La voie honnête. Outils de productivité, consoles d’admin, dashboards d’opérations internes, compagnons matériels, clients SaaS verticaux et creative tooling (Rive construit le leur sur Flutter). Flutter desktop colle. Pour les charges graphiques lourdes comme la CAO, la vidéo temps réel et l’audio numérique, Flutter gère encore le shell et dart:ffi vous fait descendre vers du C ou du Rust pour le travail lourd. Voir notre insight Flutter FFI pour voir comment le pattern hybride tourne réellement en production.
Imaginez une petite équipe qui a livré une app Flutter mobile l’an dernier. Ce trimestre, ils ont besoin d’un compagnon desktop. Pas une refonte, pas une seconde équipe, pas un nouveau framework. Ils extraient la logique métier dans un package, ajoutent un point d’entrée desktop, câblent la menu bar, et livrent. Une semaine plus tard, la version Windows tourne sur le laptop du CEO et la version macOS sur l’iMac du designer. Voilà à quoi ressemble le développement d’apps desktop cross-platform quand le framework cesse d’être dans le chemin.
Vous envisagez Flutter pour votre app desktop ?