Skip to content

Latest commit

 

History

History
930 lines (778 loc) · 47.1 KB

File metadata and controls

930 lines (778 loc) · 47.1 KB

Chapitre 7 : Solutions légères alternatives

Vue d'ensemble

Ce chapitre explore les alternatives légères aux solutions WebView classiques (Tauri, Electron, Wry) pour créer des applications desktop en Rust. Chaque moteur de rendu possède sa propre philosophie, ses forces et ses compromis. Nous analyserons en profondeur rust-webview, Servo, et Sciter, avant de proposer une matrice de décision complète pour choisir la solution la plus adaptée à vos besoins.

┌─────────────────────────────────────────────────────────────────┐
│              Écosystème des moteurs de rendu légers              │
│                                                                  │
│   ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐  │
│   │ rust-webview  │  │    Servo     │  │       Sciter         │  │
│   │              │  │              │  │                      │  │
│   │  WebView OS  │  │  Moteur Rust │  │  HTML/CSS léger      │  │
│   │  ~2 Mo       │  │  ~15-40 Mo   │  │  ~5 Mo               │  │
│   │  Minimaliste │  │  Expérimental│  │  Riche en widgets    │  │
│   └──────┬───────┘  └──────┬───────┘  └──────────┬───────────┘  │
│          │                 │                      │              │
│          ▼                 ▼                      ▼              │
│   ┌─────────────────────────────────────────────────────────┐   │
│   │           Application Desktop Rust + UI Web             │   │
│   └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Note pédagogique : Contrairement à Tauri (chapitre 4) ou Wry (chapitre 6) qui représentent des solutions matures et bien maintenues, les alternatives présentées ici occupent des niches spécifiques. Leur connaissance est essentielle pour faire des choix éclairés, notamment dans des contextes embarqués, expérimentaux ou à fortes contraintes de taille.


7.1 WebView simple avec rust-webview

Qu'est-ce que rust-webview ?

La crate web-view (souvent appelée rust-webview) est l'un des premiers projets à avoir permis d'embarquer une WebView système dans une application Rust. Elle offre une interface minimaliste pour afficher du contenu HTML/CSS/JS dans une fenêtre native, en utilisant le moteur de rendu du système d'exploitation.

┌──────────────────────────────────────────────────┐
│               Architecture rust-webview           │
│                                                    │
│  ┌──────────────────────────────────────────┐     │
│  │           Application Rust               │     │
│  │                                           │     │
│  │  ┌─────────────┐   ┌──────────────────┐  │     │
│  │  │ Logique     │   │ Callbacks Rust   │  │     │
│  │  │ métier      │◄──►│ (invoke_handler) │  │     │
│  │  └─────────────┘   └────────┬─────────┘  │     │
│  │                             │             │     │
│  └─────────────────────────────┼─────────────┘     │
│                                │                    │
│  ┌─────────────────────────────▼──────────────┐    │
│  │         WebView Système (FFI)              │    │
│  │                                             │    │
│  │  Windows: MSHTML/Edge   Linux: WebKitGTK   │    │
│  │  macOS: WKWebView                           │    │
│  └─────────────────────────────────────────────┘    │
└──────────────────────────────────────────────────┘

Moteurs sous-jacents par plateforme

Plateforme Moteur de rendu Bibliothèque native
Windows MSHTML / Edge WebView2 webview.dll (MSHTML)
macOS WebKit (WKWebView) Cocoa / WebKit.framework
Linux WebKitGTK libwebkit2gtk

Installation et configuration

Ajoutez la dépendance dans votre Cargo.toml :

[package]
name = "demo-webview"
version = "0.1.0"
edition = "2021"

[dependencies]
web-view = "0.7"
serde = { version = "1", features = ["derive"] }
serde_json = "1"

Attention : Sur Linux, vous devrez installer les dépendances système :

sudo apt install libwebkit2gtk-4.0-dev libgtk-3-dev

Application minimale

Voici une application "Hello World" complète avec rust-webview :

use web_view::*;

fn main() {
    // Création de la fenêtre WebView
    let webview = web_view::builder()
        .title("Mon Application rust-webview")
        .content(Content::Html(r#"
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <style>
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        color: white;
                    }
                    .container { text-align: center; }
                    button {
                        padding: 12px 24px;
                        font-size: 16px;
                        border: none;
                        border-radius: 8px;
                        background: white;
                        color: #764ba2;
                        cursor: pointer;
                        margin-top: 16px;
                    }
                    button:hover { opacity: 0.9; }
                </style>
            </head>
            <body>
                <div class="container">
                    <h1>Hello depuis rust-webview !</h1>
                    <p id="info">Cliquez le bouton pour appeler Rust</p>
                    <button onclick="appeler_rust()">Appeler Rust</button>
                </div>
                <script>
                    function appeler_rust() {
                        external.invoke(JSON.stringify({
                            type: "salutation",
                            nom: "Développeur Rust"
                        }));
                    }
                </script>
            </body>
            </html>
        "#))
        .size(800, 600)
        .resizable(true)
        .debug(true) // Active les DevTools en développement
        .user_data(0u32)  // Données utilisateur (compteur ici)
        .invoke_handler(|webview, arg| {
            // Réception des messages depuis JavaScript
            let message: serde_json::Value = serde_json::from_str(arg)
                .unwrap_or_default();

            if message["type"] == "salutation" {
                let nom = message["nom"].as_str().unwrap_or("inconnu");
                let compteur = webview.user_data_mut();
                *compteur += 1;

                // Exécuter du JavaScript depuis Rust
                let js = format!(
                    "document.getElementById('info').textContent = \
                     'Bonjour {} ! Appel n°{}'",
                    nom, compteur
                );
                webview.eval(&js)?;
            }
            Ok(())
        })
        .build()
        .expect("Impossible de créer la WebView");

    // Lancement de la boucle événementielle
    webview.run().expect("Erreur durant l'exécution");
}

Communication bidirectionnelle avancée

Le pattern de communication dans rust-webview repose sur deux mécanismes :

  1. JS → Rust : via external.invoke(string) qui déclenche l'invoke_handler
  2. Rust → JS : via webview.eval(js_code) qui exécute du JavaScript dans la WebView
┌──────────────┐                    ┌──────────────┐
│  JavaScript  │                    │     Rust     │
│              │                    │              │
│  external    │───invoke(json)────►│ invoke_      │
│  .invoke()   │                    │ handler()    │
│              │                    │              │
│  (fonction   │◄──eval(js_code)───│ webview      │
│   appelée)   │                    │ .eval()      │
└──────────────┘                    └──────────────┘

Exemple plus élaboré avec gestion de fichiers :

use web_view::*;
use std::fs;

#[derive(serde::Deserialize)]
#[serde(tag = "cmd")]
enum Commande {
    LireFichier { chemin: String },
    EcrireFichier { chemin: String, contenu: String },
    ListerRepertoire { chemin: String },
}

fn gerer_commande(webview: &mut WebView<()>, arg: &str) -> WVResult {
    let cmd: Commande = serde_json::from_str(arg)
        .map_err(|e| web_view::Error::Custom(
            Box::new(std::io::Error::new(std::io::ErrorKind::Other, e))
        ))?;

    match cmd {
        Commande::LireFichier { chemin } => {
            match fs::read_to_string(&chemin) {
                Ok(contenu) => {
                    let contenu_escape = contenu
                        .replace('\\', "\\\\")
                        .replace('\'', "\\'")
                        .replace('\n', "\\n");
                    webview.eval(&format!(
                        "onFichierLu('{}')", contenu_escape
                    ))?;
                }
                Err(e) => {
                    webview.eval(&format!(
                        "onErreur('Lecture impossible : {}')", e
                    ))?;
                }
            }
        }
        Commande::EcrireFichier { chemin, contenu } => {
            match fs::write(&chemin, &contenu) {
                Ok(_) => webview.eval("onFichierEcrit(true)")?,
                Err(e) => webview.eval(&format!(
                    "onErreur('Écriture impossible : {}')", e
                ))?,
            }
        }
        Commande::ListerRepertoire { chemin } => {
            let entrees: Vec<String> = fs::read_dir(&chemin)
                .map(|rd| {
                    rd.filter_map(|e| e.ok())
                        .map(|e| e.file_name().to_string_lossy().to_string())
                        .collect()
                })
                .unwrap_or_default();

            let json = serde_json::to_string(&entrees).unwrap();
            webview.eval(&format!("onRepertoireListe({})", json))?;
        }
    }
    Ok(())
}

Limites de rust-webview

Aspect Détail
Maintenance Projet peu actif depuis 2021, supplanté par Wry
Moteur Windows Utilise MSHTML (IE) par défaut — rendu obsolète
Communication String uniquement — sérialisation manuelle requise
Multi-fenêtres Non supporté nativement
Fonctionnalités OS Très limitées (pas de menus, pas de notifications)
Sécurité Pas de sandboxing, pas de CSP intégrée

Recommandation : rust-webview est utile pour comprendre les fondamentaux de l'approche WebView en Rust, mais pour un projet en production, privilégiez Wry (chapitre 6) ou Tauri (chapitre 4) qui en sont les successeurs spirituels directs.


7.2 Servo comme moteur de rendu

Présentation de Servo

Servo est un moteur de rendu web expérimental développé initialement par Mozilla Research, écrit entièrement en Rust. Contrairement aux WebView système qui délèguent au moteur du système d'exploitation, Servo est le moteur. Cela offre un contrôle total sur le rendu, la parallélisation et la sécurité mémoire.

┌─────────────────────────────────────────────────────────────────┐
│                    Architecture de Servo                         │
│                                                                  │
│  ┌────────────┐  ┌────────────┐  ┌────────────┐  ┌───────────┐ │
│  │   Parseur  │  │   Style    │  │   Layout   │  │  Rendu    │ │
│  │ HTML/CSS   │──►│  Résolution│──►│  (Parallèle│──►│ (WebRender│ │
│  │            │  │ (Stylo)    │  │   Taffy)   │  │  / GPU)   │ │
│  └────────────┘  └────────────┘  └────────────┘  └───────────┘ │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │                    Couche Embedding                        │  │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌───────────┐ │  │
│  │  │ Fenêtrage│  │ Événements│  │ Réseau   │  │ JavaScript│ │  │
│  │  │ (winit)  │  │ (input)  │  │ (reqwest) │  │(SpiderMnky│ │  │
│  │  └──────────┘  └──────────┘  └──────────┘  └───────────┘ │  │
│  └────────────────────────────────────────────────────────────┘  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐  │
│  │  Composants Rust natifs : Rayon, Crossbeam, Serde, etc.   │  │
│  └────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

Composants clés de Servo

Composant Rôle Technologie
Stylo Résolution CSS parallèle Intégré dans Firefox
WebRender Rendu GPU via OpenGL/Vulkan Intégré dans Firefox
Taffy Moteur de layout (Flexbox, Grid) Crate Rust standalone
SpiderMonkey Moteur JavaScript (de Firefox) C++ via FFI
surfman Abstraction de surface GPU Rust natif
mozjs Bindings Rust pour SpiderMonkey FFI Rust ↔ C++

Utilisation de Servo comme bibliothèque embarquée

Servo peut être compilé comme une bibliothèque et intégré dans votre application Rust. Voici comment configurer un projet basique :

# Cargo.toml — Attention : la compilation de Servo est complexe
[package]
name = "servo-desktop-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
# Servo n'est pas une simple crate — il nécessite un build spécifique.
# On utilise l'API d'embedding de Servo :
servo = { git = "https://github.com/servo/servo", features = ["embedding"] }
winit = "0.30"

Avertissement : La compilation de Servo est une opération lourde (30 min à 1h+). Elle nécessite des dépendances système spécifiques et un environnement correctement configuré. Consultez le guide de build officiel.

Exemple conceptuel : Embedding de Servo

// NOTE : API simplifiée pour illustrer le concept.
// L'API réelle de Servo évolue fréquemment.

use servo::compositing::windowing::WindowMethods;
use servo::config::opts;
use servo::servo_url::ServoUrl;
use servo::Servo;

/// Structure représentant notre fenêtre d'application.
struct FenetreApp {
    titre: String,
    largeur: u32,
    hauteur: u32,
}

impl FenetreApp {
    fn new(titre: &str, largeur: u32, hauteur: u32) -> Self {
        Self {
            titre: titre.to_string(),
            largeur,
            hauteur,
        }
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialisation des options de Servo
    let mut opts = opts::default_opts();
    opts.headless = false;
    opts.url = Some(ServoUrl::parse("data:text/html,<h1>Hello Servo!</h1>")?);

    // Création de la fenêtre native avec winit
    let event_loop = winit::event_loop::EventLoop::new()?;
    let window = winit::window::WindowBuilder::new()
        .with_title("Application Servo + Rust")
        .with_inner_size(winit::dpi::LogicalSize::new(1024, 768))
        .build(&event_loop)?;

    // Initialisation de Servo avec notre fenêtre
    // (pseudo-code — l'API réelle requiert une implémentation
    //  complète de WindowMethods et EmbedderMethods)
    println!("Servo initialisé avec succès !");
    println!("Fenêtre : {}x{}", 1024, 768);

    // Boucle événementielle
    event_loop.run(move |event, elwt| {
        match event {
            winit::event::Event::WindowEvent {
                event: winit::event::WindowEvent::CloseRequested,
                ..
            } => {
                elwt.exit();
            }
            winit::event::Event::AboutToWait => {
                // Ici, on demanderait à Servo de rendre la frame suivante
                window.request_redraw();
            }
            _ => {}
        }
    })?;

    Ok(())
}

Servo et le rendu parallèle

L'un des atouts majeurs de Servo est sa capacité à paralléliser le rendu web. Là où les moteurs traditionnels (Blink, WebKit) sont majoritairement mono-thread pour le layout et le style, Servo exploite pleinement le parallélisme :

┌─────────────────────────────────────────────────────────────┐
│              Pipeline de rendu parallèle (Servo)             │
│                                                              │
│  Thread 1: ──[Parse HTML]──[Style nœud A]──[Layout A]──►   │
│  Thread 2: ────────────────[Style nœud B]──[Layout B]──►   │
│  Thread 3: ────────────────[Style nœud C]──[Layout C]──►   │
│  Thread 4: ────────────────[Style nœud D]──[Layout D]──►   │
│                                                    │         │
│                                                    ▼         │
│                                            ┌──────────────┐ │
│                                            │  Composition │ │
│                                            │  GPU (rendu) │ │
│                                            └──────────────┘ │
│                                                              │
│  Versus moteur classique (mono-thread) :                     │
│  Thread 1: ──[Parse]──[Style A]──[B]──[C]──[D]──[Layout]──►│
└─────────────────────────────────────────────────────────────┘

Avantages et inconvénients de Servo

Critère Avantage Inconvénient
Langage 100% Rust — mêmes garanties que votre app Compilation très longue
Parallélisme Layout et style parallèles Surcoût mémoire multi-thread
Contrôle Contrôle total du moteur de rendu API instable, documentation rare
Taille Moteur complet embarqué (~15-40 Mo) Plus lourd qu'une WebView système
Compatibilité web Support CSS/HTML en progression Pas encore à parité avec Chrome/Firefox
Sécurité Mémoire sûre grâce à Rust SpiderMonkey reste en C++
Communauté Soutien de Linux Foundation depuis 2023 Communauté plus petite que Chromium/WebKit

Cas d'usage pertinents pour Servo

  • Kiosques et bornes interactives : contrôle total sur le rendu, pas de dépendance au navigateur système
  • Applications embarquées : Servo peut tourner sans serveur X11 (rendu headless)
  • Recherche et expérimentation : tester de nouvelles approches de rendu web en Rust
  • Produits nécessitant un rendu web cohérent : le même moteur sur toutes les plateformes

Perspective : Depuis son transfert à la Linux Foundation en 2023, Servo connaît un regain d'activité. Le projet vise à devenir un moteur d'embedding viable, ce qui en ferait une alternative 100% Rust à Chromium Embedded Framework (CEF). Restez attentif aux évolutions de l'API d'embedding.


7.3 Sciter avec Rust

Présentation de Sciter

Sciter est un moteur de rendu HTML/CSS propriétaire (mais gratuit pour usage personnel) conçu spécifiquement pour les interfaces d'applications desktop. Contrairement aux WebView classiques qui embarquent un navigateur complet, Sciter n'implémente que le sous-ensemble HTML/CSS utile pour les UI, avec des extensions spécifiques comme le langage de script TIScript (un dialecte de JavaScript).

┌─────────────────────────────────────────────────────────────────┐
│                  Architecture Sciter + Rust                      │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │                  Application Rust                        │   │
│  │                                                           │   │
│  │  ┌──────────────┐      ┌─────────────────────────────┐   │   │
│  │  │ Logique      │      │   rust-sciter (bindings)    │   │   │
│  │  │ métier Rust  │◄────►│                             │   │   │
│  │  │              │      │   EventHandler trait        │   │   │
│  │  └──────────────┘      └──────────────┬──────────────┘   │   │
│  └───────────────────────────────────────┼──────────────────┘   │
│                                          │ FFI                   │
│  ┌───────────────────────────────────────▼──────────────────┐   │
│  │              Sciter Engine (DLL/dylib/so)                 │   │
│  │                                                           │   │
│  │  ┌──────────┐  ┌──────────┐  ┌────────┐  ┌───────────┐  │   │
│  │  │ Parseur  │  │ Layout   │  │ Rendu  │  │ TIScript  │  │   │
│  │  │ HTML/CSS │  │ Engine   │  │ Direct │  │ / JS      │  │   │
│  │  └──────────┘  └──────────┘  └────────┘  └───────────┘  │   │
│  │                                                           │   │
│  │  Taille totale : ~5 Mo (vs ~80+ Mo pour Chromium)        │   │
│  └───────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Installation de rust-sciter

[package]
name = "demo-sciter"
version = "0.1.0"
edition = "2021"

[dependencies]
sciter-rs = "0.5"

Prérequis : Téléchargez la bibliothèque Sciter native depuis sciter.com et placez le fichier .dll (Windows), .dylib (macOS) ou .so (Linux) dans votre répertoire de travail ou dans le PATH système.

Application Sciter de base

extern crate sciter;

use sciter::Value;

// Structure qui gère les événements entre l'UI et Rust
struct GestionnaireApp;

impl GestionnaireApp {
    // Méthode appelable depuis l'HTML/TIScript
    fn calculer_somme(&self, a: f64, b: f64) -> Value {
        let resultat = a + b;
        println!("[Rust] Calcul : {} + {} = {}", a, b, resultat);
        Value::from(resultat)
    }

    fn obtenir_infos_systeme(&self) -> Value {
        let info = format!(
            "OS: {} | Arch: {} | CPUs: {}",
            std::env::consts::OS,
            std::env::consts::ARCH,
            std::thread::available_parallelism()
                .map(|n| n.get())
                .unwrap_or(1)
        );
        Value::from(info.as_str())
    }
}

// Implémentation du trait EventHandler pour recevoir les appels
impl sciter::EventHandler for GestionnaireApp {
    sciter::dispatch_script_call! {
        fn calculer_somme(f64, f64);
        fn obtenir_infos_systeme();
    }
}

fn main() {
    // Créer la fenêtre Sciter
    let mut frame = sciter::Window::new();

    // Charger le HTML de l'interface
    frame.load_html(br#"
        <html>
        <head>
            <style>
                body {
                    font-family: system;
                    padding: 20px;
                    background: #1a1a2e;
                    color: #e0e0e0;
                }
                .card {
                    background: #16213e;
                    border-radius: 8px;
                    padding: 20px;
                    margin: 10px 0;
                    box-shadow: 0 4px 6px rgba(0,0,0,0.3);
                }
                input[type=text] {
                    padding: 8px 12px;
                    border: 1px solid #0f3460;
                    border-radius: 4px;
                    background: #0a0a23;
                    color: #e0e0e0;
                    width: 100px;
                }
                button {
                    padding: 8px 16px;
                    background: #e94560;
                    color: white;
                    border: none;
                    border-radius: 4px;
                    cursor: pointer;
                }
                button:hover { background: #c73750; }
                #resultat { color: #53d769; font-weight: bold; }
            </style>
            <script type="text/tiscript">
                function calculer() {
                    var a = parseFloat($(#val_a).value) || 0;
                    var b = parseFloat($(#val_b).value) || 0;
                    var resultat = view.calculer_somme(a, b);
                    $(#resultat).text = "Résultat : " + resultat.toString();
                }

                function afficherInfos() {
                    var infos = view.obtenir_infos_systeme();
                    $(#infos_systeme).text = infos;
                }

                // Appeler au chargement
                self.ready = function() {
                    afficherInfos();
                };
            </script>
        </head>
        <body>
            <h1>🔧 Demo Sciter + Rust</h1>

            <div class="card">
                <h2>Calculatrice</h2>
                <input|text(val_a) placeholder="Valeur A" />
                <span> + </span>
                <input|text(val_b) placeholder="Valeur B" />
                <button onclick="calculer()">Calculer (via Rust)</button>
                <p id="resultat">En attente...</p>
            </div>

            <div class="card">
                <h2>Informations système</h2>
                <p id="infos_systeme">Chargement...</p>
            </div>
        </body>
        </html>
    "#, Some("example://app/main.html"));

    // Enregistrer notre gestionnaire d'événements
    frame.event_handler(GestionnaireApp);

    // Configurer la fenêtre
    frame.set_title("Application Sciter + Rust");
    frame.run_app();
}

Communication Rust ↔ Sciter : le pattern EventHandler

Sciter propose un mécanisme de communication plus structuré que rust-webview grâce au trait EventHandler et à la macro dispatch_script_call! :

use sciter::{Value, HELEMENT};

struct GestionnaireAvance {
    compteur: std::cell::Cell<u32>,
    historique: std::cell::RefCell<Vec<String>>,
}

impl GestionnaireAvance {
    fn new() -> Self {
        Self {
            compteur: std::cell::Cell::new(0),
            historique: std::cell::RefCell::new(Vec::new()),
        }
    }

    // Fonctions exposées à TIScript
    fn incrementer(&self) -> Value {
        let n = self.compteur.get() + 1;
        self.compteur.set(n);
        self.historique.borrow_mut().push(format!("Incrémenté à {}", n));
        Value::from(n as i32)
    }

    fn obtenir_historique(&self) -> Value {
        let hist = self.historique.borrow();
        let mut arr = Value::new();
        for (i, entry) in hist.iter().enumerate() {
            arr.set_item(i, Value::from(entry.as_str()));
        }
        arr
    }

    fn rechercher_fichier(&self, motif: String) -> Value {
        // Exemple d'opération système depuis l'UI
        let resultats: Vec<String> = std::fs::read_dir(".")
            .map(|rd| {
                rd.filter_map(|e| e.ok())
                    .filter(|e| {
                        e.file_name()
                            .to_string_lossy()
                            .contains(&motif)
                    })
                    .map(|e| e.path().display().to_string())
                    .collect()
            })
            .unwrap_or_default();

        let json = serde_json::to_string(&resultats).unwrap_or_default();
        Value::from(json.as_str())
    }
}

impl sciter::EventHandler for GestionnaireAvance {
    sciter::dispatch_script_call! {
        fn incrementer();
        fn obtenir_historique();
        fn rechercher_fichier(String);
    }
}

Fonctionnalités spécifiques à Sciter

Sciter offre plusieurs avantages uniques pour les applications desktop :

Fonctionnalité Description
CSS natifs étendus Flexbox étendu, flow layouts, animations natives
Comportements intégrés Menus, listes virtualisées, éditeurs riches — sans JS
TIScript Dialecte JavaScript optimisé pour les UI desktop
Rendu direct Pas de couche navigateur — rendu GPU Direct2D / Skia
Taille minimale DLL de ~5 Mo vs ~80+ Mo pour Chromium
Mode Lite Version « Sciter.Lite » encore plus compacte (~3 Mo)
Graphiques intégrés Support SVG, Canvas 2D, vidéo sans dépendances supplémentaires

Limites de Sciter

  • Licence propriétaire : gratuit pour usage personnel/évaluation, licence commerciale requise en production
  • Pas de standard web complet : sous-ensemble HTML/CSS — certaines fonctionnalités web manquent
  • TIScript ≠ JavaScript : syntaxe similaire mais différences qui complexifient la migration
  • Communauté restreinte : moins de ressources, tutoriels et bibliothèques que l'écosystème web
  • Futur incertain : développé par une seule personne (Andrew Fedoniouk)

Cas d'usage idéal : Sciter excelle pour les applications desktop qui nécessitent une UI riche avec une empreinte mémoire minimale et ne visent pas le web. C'est un excellent choix pour les outils internes, les utilitaires système ou les applications embarquées où chaque mégaoctet compte.


7.4 Choix du moteur selon les besoins

Matrice de comparaison complète

Cette section synthétise les informations des chapitres 4 à 7 pour vous aider à choisir la bonne solution.

┌────────────────────────────────────────────────────────────────────────────┐
│                    Spectre des solutions desktop Rust                      │
│                                                                            │
│  Léger ◄─────────────────────────────────────────────────────► Complet    │
│                                                                            │
│  rust-webview   Wry   Sciter   Tauri   Servo   Dioxus   Electron         │
│  (~2 Mo)      (~3 Mo) (~5 Mo)  (~8 Mo) (~20 Mo) (~10 Mo) (~150 Mo)      │
│                                                                            │
│  Simple ◄────────────────────────────────────────────────────► Riche      │
│                                                                            │
│  Minimal ◄──────────────────────────────────────────────────► Écosystème  │
│  (DIY)                                                        (Plugins)   │
└────────────────────────────────────────────────────────────────────────────┘

Tableau comparatif détaillé

Critère rust-webview Servo Sciter Wry Tauri Electron
Taille binaire ~2 Mo ~15-40 Mo ~5 Mo ~3 Mo ~8 Mo ~150+ Mo
RAM au repos ~15 Mo ~60 Mo ~20 Mo ~25 Mo ~30 Mo ~100+ Mo
Compat. web Système Partielle Sous-ens. Système Système Chromium
Multi-plateforme ✅ ✅ ✅ ✅ ✅ ✅
Multi-fenêtres ❌ ⚠️ Limité ✅ ✅ ✅ ✅
Menus natifs ❌ ❌ ✅ ✅ ✅ ✅
Notifications ❌ ❌ ⚠️ ⚠️ ✅ ✅
Auto-update ❌ ❌ ❌ ❌ ✅ ✅
Écosystème plugins ❌ ❌ ⚠️ ❌ ✅ ✅✅
Sécurité (sandbox) ❌ ⚠️ ⚠️ ⚠️ ✅ ✅
Maturité ⚠️ Archived ⚠️ Expér. ✅ Stable ✅ Stable ✅ Mature ✅✅ Mature
100% Rust ✅ ✅ (moteur) ❌ (DLL) ✅ ✅ ❌ (Node)
Docs / Communauté ⚠️ Faible ⚠️ Faible ⚠️ Moyenne ✅ Bonne ✅✅ ✅✅✅

Arbre de décision

Utilisez cet arbre pour guider votre choix initial :

                        Votre projet nécessite-t-il
                        une application desktop Rust ?
                                    │
                                    ▼
                    ┌───────────────────────────────┐
                    │  Avez-vous besoin d'un rendu  │
                    │  web standard (HTML/CSS/JS) ? │
                    └──────────────┬────────────────┘
                           ┌───────┴───────┐
                          OUI             NON
                           │               │
                           ▼               ▼
              ┌────────────────────┐   Voir Partie III :
              │ Taille binaire     │   Dioxus, Slint, Iced,
              │ critique (< 10 Mo)?│   egui, GTK-rs...
              └─────────┬──────────┘
                 ┌──────┴──────┐
                OUI           NON
                 │             │
                 ▼             ▼
    ┌────────────────┐  ┌──────────────────┐
    │ Fonctionnalités│  │    Tauri         │
    │ OS avancées ?  │  │ (Recommandé)     │
    └───────┬────────┘  └──────────────────┘
       ┌────┴────┐
      OUI       NON
       │         │
       ▼         ▼
   Sciter    ┌────────────────────┐
   (si UI    │ Contrôle total     │
    riche)   │ du moteur requis ? │
             └───────┬────────────┘
                ┌────┴────┐
               OUI       NON
                │         │
                ▼         ▼
             Servo      Wry
           (expérim.)  (minimaliste)

Scénarios concrets de choix

Scénario 1 : Utilitaire système interne (< 5 Mo)

Contexte : Vous développez un outil de monitoring réseau pour usage interne.

Choix recommandé : Wry ou Sciter

// Avec Wry — UI minimaliste pour monitoring
// Voir chapitre 6 pour le code complet

// Critères de décision :
// ✅ Taille < 5 Mo → Wry (~3 Mo) ou Sciter (~5 Mo)
// ✅ Pas besoin d'écosystème plugins
// ✅ Une seule fenêtre suffit
// ❌ Pas besoin d'auto-update

Scénario 2 : Application commerciale grand public

Contexte : SaaS avec desktop companion, auto-update, notifications.

Choix recommandé : Tauri (voir chapitre 4)

// Critères de décision :
// ✅ Auto-update nécessaire → Tauri
// ✅ Écosystème de plugins riche
// ✅ Sécurité : sandboxing et CSP
// ✅ Communauté et documentation
// ⚠️ Taille acceptable (~8 Mo)

Scénario 3 : Prototype de recherche avec rendu custom

Contexte : Projet de recherche sur le rendu web parallèle.

Choix recommandé : Servo

// Critères de décision :
// ✅ Contrôle total du pipeline de rendu
// ✅ Parallélisation du layout/style
// ✅ 100% Rust (sauf SpiderMonkey)
// ⚠️ API instable — acceptable pour la recherche
// ⚠️ Compilation longue — acceptable pour un prototype

Scénario 4 : Application embarquée IoT avec écran tactile

Contexte : Interface pour un dispositif industriel, ressources très limitées.

Choix recommandé : Sciter Lite ou Slint (chapitre 9)

// Critères de décision :
// ✅ Empreinte mémoire minimale (< 20 Mo RAM)
// ✅ Taille binaire ultra-compacte (< 5 Mo)
// ✅ Rendu direct sans navigateur
// ✅ Widgets natifs pour interfaces industrielles
// ❌ Pas besoin de compatibilité web standard

Matrice de décision pondérée

Pour un choix structuré, attribuez des poids (1-5) à chaque critère selon votre projet, puis multipliez par le score de chaque solution :

┌──────────────────────┬───────┬──────────┬───────┬───────┬───────┬────────┐
│ Critère (poids 1-5)  │ Poids │rust-wview│ Servo │Sciter │  Wry  │ Tauri  │
├──────────────────────┼───────┼──────────┼───────┼───────┼───────┼────────┤
│ Taille minimale      │  ?    │   5/5    │  2/5  │  4/5  │  5/5  │  3/5   │
│ Compatibilité web    │  ?    │   3/5    │  2/5  │  2/5  │  4/5  │  4/5   │
│ APIs système         │  ?    │   1/5    │  1/5  │  3/5  │  2/5  │  5/5   │
│ Maturité / Stabilité │  ?    │   2/5    │  2/5  │  3/5  │  4/5  │  5/5   │
│ Documentation        │  ?    │   2/5    │  2/5  │  3/5  │  4/5  │  5/5   │
│ Performance rendu    │  ?    │   3/5    │  4/5  │  4/5  │  3/5  │  3/5   │
│ 100% Open Source     │  ?    │   5/5    │  5/5  │  2/5  │  5/5  │  5/5   │
│ Sécurité             │  ?    │   1/5    │  3/5  │  2/5  │  3/5  │  5/5   │
├──────────────────────┼───────┼──────────┼───────┼───────┼───────┼────────┤
│ TOTAL (Poids × Note) │       │  Σ = ?   │ Σ = ? │ Σ = ? │ Σ = ? │ Σ = ?  │
└──────────────────────┴───────┴──────────┴───────┴───────┴───────┴────────┘

Instructions : Remplacez les "?" dans la colonne Poids par vos priorités (1-5).
Multipliez chaque poids par la note, puis additionnez pour obtenir le total.
La solution avec le score le plus élevé est votre meilleur candidat.

Recommandations finales par profil

Profil développeur Solution recommandée Alternative
Débutant Rust desktop Tauri + Yew Dioxus Desktop
Développeur embarqué/IoT Sciter Lite ou Slint Servo (expérimental)
Startup — MVP rapide Tauri + Yew Wry (si ultra-léger)
Entreprise — app critique Tauri (v2) Electron + napi-rs
Chercheur / Académique Servo Iced / egui
Migration depuis Electron Tauri Wry + migration
Contrainte taille extrême Wry rust-webview (si legacy)

Résumé du chapitre

Ce chapitre a exploré trois alternatives légères pour créer des applications desktop en Rust :

  1. rust-webview : la solution historique, minimaliste mais désormais archivée. Elle reste utile pour comprendre les fondamentaux de l'approche WebView mais ne devrait plus être choisie pour un nouveau projet.

  2. Servo : le moteur de rendu web 100% Rust, idéal pour la recherche et les cas nécessitant un contrôle total du pipeline de rendu. Son transfert à la Linux Foundation lui donne un avenir prometteur, mais il n'est pas encore prêt pour la production.

  3. Sciter : un moteur HTML/CSS léger et spécialisé pour le desktop, offrant un excellent rapport fonctionnalités/taille. Sa licence propriétaire et sa dépendance à un développeur unique en font un choix à évaluer avec prudence.

La section 7.4 fournit des outils de décision concrets — arbre de décision, matrice pondérée, scénarios — pour choisir la solution la plus adaptée à votre contexte.

Points clés à retenir

  • Il n'existe pas de solution universelle : chaque moteur répond à des contraintes spécifiques
  • Tauri reste le choix par défaut pour la majorité des projets desktop Rust basés sur le web
  • La taille binaire n'est pas le seul critère : maturité, sécurité et écosystème comptent autant
  • L'écosystème Rust desktop évolue rapidement : réévaluez vos choix régulièrement

Chapitre suivant : Chapitre 8 — Dioxus Desktop : le concurrent direct

Dans la Partie III, nous quittons les solutions WebView pour explorer les frameworks de rendu natif en Rust. Dioxus Desktop, avec son approche React-like et son rendu via Tao/Wry, représente un pont naturel entre le monde web et le desktop natif.