openpencil/packages/docs/fr/guide/comparison.md

250 lines
12 KiB
Markdown
Raw Normal View History

# Open Pencil vs Penpot : Comparaison d'architecture et de performances
Pourquoi comparer ? OpenPencil existe parce que les plateformes de design fermées contrôlent ce qui est possible. Comprendre les différences architecturales montre ce qu'une alternative ouverte et local-first peut faire différemment.
::: info Renderer WASM de Penpot
Penpot 2.x inclut un renderer Rust/Skia WASM (`render-wasm/v1`) activable via les flags du serveur ou le paramètre URL `?wasm=true`. Le renderer SVG reste le défaut. Cette page couvre les deux.
:::
## 1. Échelle et taille du code
| Métrique | Open Pencil | Penpot |
|----------|-------------|--------|
| LOC total | **~26 000** | **~299 000** |
| Fichiers source | ~143 | ~2 900 |
| Langages | TypeScript, Vue | Clojure, ClojureScript, Rust, JS, SQL, SCSS |
| Moteur de rendu | ~3 200 LOC (TS, 10 plików) | 22 000 LOC (Rust/Skia WASM) |
| Code UI | ~4 500 LOC | ~175 000 LOC (CLJS + SCSS) |
| Backend | Aucun (local-first) | 32 600 LOC + 151 fichiers SQL |
| Ratio LOC | **1×** | **~11×** |
Open Pencil est **~11× plus petit** — et c'est tout l'intérêt. Ce n'est pas une simplification ; c'est une architecture fondamentalement différente.
## 2. Architecture
### Open Pencil : Client monolithique
```
┌─────────────────────────────────┐
│ Tauri (shell natif) │
│ ┌───────────────────────────┐ │
│ │ Vue 3 + TypeScript │ │
│ │ ┌─────────┐ ┌──────────┐│ │
│ │ │ Editor │ │ Kiwi ││ │
│ │ │ Store │ │ Codec ││ │
│ │ └────┬─────┘ └──────────┘│ │
│ │ │ │ │
│ │ ┌────▼────────────────┐ │ │
│ │ │ Scene Graph (TS) │ │ │
│ │ │ Map<string, Node> │ │ │
│ │ └────┬────────────────┘ │ │
│ │ │ │ │
│ │ ┌────▼────┐ ┌──────────┐│ │
│ │ │ Skia │ │ Yoga ││ │
│ │ │CanvasKit│ │ Layout ││ │
│ │ │ (WASM) │ │ (WASM) ││ │
│ │ └─────────┘ └──────────┘│ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
```
**Tout dans un seul processus.** Pas de serveur, pas de base de données, pas de Docker.
### Penpot : Client-serveur distribué
```
┌───────────────────────────────────────────────────────┐
│ Docker Compose │
│ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ │
│ │ Frontend │ │ Backend │ │ Exporter │ │
│ │ ClojureScript│ │ Clojure │ │ (Chromium) │ │
│ │ shadow-cljs │ │ JVM │ │ │ │
│ │ ┌─────────┐ │ │ ┌────────┐ │ └──────────────┘ │
│ │ │render- │ │ │ │Postgres│ │ │
│ │ │wasm │ │ │ │Valkey │ │ ┌──────────────┐ │
│ │ │(Rust→ │ │ │ │ MinIO │ │ │ MCP │ │
│ │ │ Skia │ │ │ └────────┘ │ │ Server │ │
│ │ │ WASM) │ │ │ │ └──────────────┘ │
│ │ └─────────┘ │ │ │ │
│ └──────────────┘ └─────────────┘ │
└───────────────────────────────────────────────────────┘
```
**Minimum 5+ services.** PostgreSQL, Redis (Valkey), MinIO, un backend JVM, un exporteur Node.js (Chromium headless), plus le frontend ClojureScript.
### Verdict : Architecture
L'architecture monoprocessus d'Open Pencil élimine : la latence réseau, l'overhead de sérialisation aux frontières de services, la complexité d'orchestration de conteneurs et l'overhead de requêtes base de données.
## 3. Pipeline de rendu
### Open Pencil : TS → CanvasKit WASM (direct)
```typescript
renderSceneToCanvas(canvas, graph, pageId) {
this.fillPaint.setColor(...)
canvas.drawRRect(rrect, this.fillPaint)
}
```
- **1 franchissement de frontière :** TS → WASM (CanvasKit)
- Le graphe de scène vit dans le heap JS — pas de sérialisation pour le rendu
- 1 646 LOC de renderer au total
### Penpot : JS (compilé depuis CLJS) → Rust WASM → Skia
```
ClojureScript (compilé en JS)
→ décomposer en primitives + empaqueter en binaire en mémoire linéaire WASM
→ Rust WASM (via Emscripten C FFI)
→ skia-safe (bindings Rust Skia)
→ Skia (WebGL)
```
Quand désactivé (défaut), les formes sont rendues comme un arbre DOM SVG. Quand activé, système de rendu par tuiles avec 11 surfaces et cache de 1024 entrées.
### Verdict : Rendu
| Aspect | Open Pencil | Penpot |
|--------|-------------|--------|
| Frontière JS→WASM | Direct (objets TS) | Empaquetage binaire (104 octets par forme) |
| Modèle de rendu | Immédiat/redessin complet | Cache par tuiles |
| Gestion des surfaces | 1 surface | 11 surfaces |
| Overhead mémoire | Faible (pas de cache tuiles) | Élevé (1024 entrées cache) |
| Complexité du code | 1 646 LOC | 22 000 LOC |
| Code unsafe | Aucun | État global `unsafe` |
## 4. Graphe de scène et modèle de données
### Open Pencil
```typescript
nodes: Map<string, SceneNode>
// 29 types de nœuds du schéma Kiwi de Figma
// ~390 champs par NodeChange (compatible Figma)
```
- Interfaces TypeScript avec types stricts
- GUIDs au format `sessionID:localID` de Figma
### Penpot
- Données réparties dans `common/` (49 600 LOC de .cljc)
- Validation de schéma au runtime (Malli)
- Les données doivent traverser la frontière CLJS→Rust pour le rendu
### Verdict : Modèle de données
Open Pencil réutilise le schéma éprouvé de Figma directement en TypeScript — zéro traduction. Penpot maintient son propre système de types à travers trois langages.
## 5. Moteur de layout
### Open Pencil : Yoga WASM (314 LOC)
```typescript
import Yoga from 'yoga-layout'
const root = Yoga.Node.create()
root.setFlexDirection(FlexDirection.Row)
root.calculateLayout()
```
314 lignes au total. Synchrone, dans le processus.
### Penpot : Double implémentation
Penpot maintient **deux moteurs de layout indépendants** (CLJS et Rust) qui doivent produire des résultats identiques. ~3 000+ LOC de code layout personnalisé dupliqué.
### Verdict : Layout
Open Pencil délègue à Yoga (utilisé par React Native sur des milliards d'appareils) en 314 lignes.
## 6. Format de fichier et compatibilité Figma
### Open Pencil
- **Format binaire Kiwi natif** — même sérialisation que Figma
- Import direct `.fig`, collage depuis le presse-papiers Figma
- Compatible avec le protocole multiplayer de Figma
### Penpot
- **Archive ZIP** (`.penpot`) avec manifestes JSON et assets binaires
- Pas d'import natif `.fig`
- Trois versions de format avec système de migration
### Verdict : Format de fichier
Open Pencil a un avantage significatif — il peut lire les fichiers Figma nativement et coller les données du presse-papiers Figma.
## 7. Gestion d'état et annulation
### Open Pencil
```typescript
// 110 LOC — patron de commande inverse
class UndoManager {
apply(entry) { entry.forward(); this.undoStack.push(entry) }
undo() { entry.inverse(); this.redoStack.push(entry) }
}
```
110 lignes. Closures forward/inverse avec état minimal.
### Penpot
Gestion d'état via Potok (bibliothèque Redux-like pour atomes ClojureScript). Undo stocke des vecteurs de changements inverses (max 50 entrées), avec auto-expiration après 20 secondes.
## 8. Expérience développeur
| Métrique | Open Pencil | Penpot |
|----------|-------------|--------|
| Setup dev | `bun install && bun dev` | Docker Compose + JVM + Node + Rust |
| Rechargement à chaud | Vite HMR (~50ms) | shadow-cljs (secondes) |
| Vérification de types | TypeScript (strict) | Runtime (schémas Malli) |
| Temps de build | <5s (Vite) | Minutes (JVM + CLJS + Rust WASM) |
| Barrière première contribution | Basse (TS/Vue) | Haute (Clojure + Rust + Docker) |
| Desktop | Tauri v2 (~5Mo) | N/A (navigateur uniquement) |
| Bassin de recrutement | Massif (devs TS/Vue) | Petit (ClojureScript + Rust) |
## 9. Caractéristiques de performance
| Scénario | Open Pencil | Penpot |
|----------|-------------|--------|
| Démarrage à froid | <2s (chargement WASM) | 10s+ (serveur + client + WASM) |
| Latence d'opération | <1ms (dans le processus) | 10-50ms (aller-retour réseau) |
| Frame de rendu | Appel Skia direct | CLJS→JS→WASM FFI→Skia |
| Mémoire de base | ~50Mo (onglet navigateur) | ~300Mo+ (JVM + Postgres + Valkey + navigateur) |
| Capacité hors ligne | Complète (local-first) | Aucune (dépend du serveur) |
| Rendu 10K formes | Une passe, sans cache | Par tuiles avec 11 surfaces |
## 10. Ce que Penpot fait mieux
1. **Collaboration serveur** — édition multi-utilisateurs centralisée avec WebSockets, comptes et contrôle d'accès
2. **Export PDF serveur** — service d'export Chromium headless pour PDF (Open Pencil exporte déjà en SVG nativement)
3. **Système de plugins** — API complète avec exécution sandboxée
4. **Tokens de design** — support natif des design tokens
5. **CSS Grid layout** — implémentation personnalisée (Open Pencil attend Yoga Grid)
6. **Self-hosting** — déploiement Docker pour les équipes
7. **Maturité** — années d'utilisation en production
## 11. Scripting et extensibilité
OpenPencil inclut une [commande `eval`](/programmable/cli/scripting) offrant une API Plugin compatible Figma pour le scripting headless. De plus, 90 outils IA sont disponibles via le chat intégré, le serveur MCP (stdio + HTTP) et le CLI. Penpot a un système de plugins avec exécution sandboxée mais pas d'API de scripting headless ni d'intégration MCP.
## Résumé
| Dimension | Gagnant | Pourquoi |
|-----------|---------|----------|
| **Simplicité architecturale** | Open Pencil | Un processus vs 5+ services |
| **Performance de rendu** | Open Pencil | CanvasKit direct vs SVG DOM (défaut) ou WASM empaqueté |
| **Maintenabilité du code** | Open Pencil | ~26K LOC en 1 langage vs 299K en 4+ |
| **Compatibilité Figma** | Open Pencil | Codec Kiwi natif vs pas de support .fig |
| **Onboarding développeur** | Open Pencil | TS/Vue vs Clojure/Rust/Docker |
| **Expérience desktop** | Open Pencil | Tauri natif vs navigateur uniquement |
| **Moteur de layout** | Open Pencil | Yoga (éprouvé) vs double implémentation |
| **Collaboration** | Égalité | Penpot : serveur avec contrôle d'accès ; Open Pencil : P2P via Trystero + Yjs |
| **Self-hosting** | Penpot | Prêt Docker vs desktop uniquement |
| **Maturité écosystème** | Penpot | Années de production vs stade précoce |
Open Pencil est architecturalement plus léger — un renderer CanvasKit monoprocessus en ~26K LOC TypeScript, compatible Figma par conception. Penpot est une plateforme full-stack avec ~299K LOC. Open Pencil a le scripting headless, **90 outils AI/MCP**, export SVG et une app desktop native.