openpencil/packages/docs/ru/guide/comparison.md
Danila Poyarkov e5b147148e Add AI & Automation docs section, CLI reference, formatting fixes
New 'AI & Automation' top-level nav section with 9 pages:
- AI Chat: setup, 87 tools, example prompts
- Collaboration: room sharing, cursors, follow mode
- JSX Renderer: elements, style props, visual diffing
- CLI (4 pages): inspecting, exporting, analyzing, scripting
- MCP Server: moved from Reference, setup + 90 tools

New CLI reference page in Reference with all 12 commands,
every option, alias, and default value.

Formatting fixes across all 7 locales:
- Wrap enum values in backticks (FRAME, SOLID, ROUND, etc.)
- Fix single-backtick code blocks → triple backticks
- Use <kbd> for all keyboard shortcuts
- Remove implementation details from user guide
- Delete stale eval-command.md and mcp-tools.md (14 files)
- Update dead links to new locations
2026-03-08 18:25:35 +03:00

23 KiB
Raw Blame History

OpenPencil vs Penpot: сравнение архитектуры и производительности

Зачем сравнивать? OpenPencil существует, потому что закрытые дизайн-платформы ограничивают возможности. Понимание архитектурных различий показывает, что может предложить открытая, локальная альтернатива.

::: info WASM-рендерер Penpot Penpot 2.x включает Rust/Skia WASM рендерер (render-wasm/v1), который можно включить через серверные флаги или параметр ?wasm=true в URL. Старый SVG-рендерер остаётся по умолчанию. На этой странице рассматриваются оба варианта. :::

1. Масштаб и размер кодовой базы

Метрика OpenPencil Penpot
Всего строк кода ~26 000 ~299 000
Файлов исходного кода ~143 ~2 900
Языки TypeScript, Vue Clojure, ClojureScript, Rust, JS, SQL, SCSS
Движок рендеринга ~3 200 строк (TS, 10 файлов) 22 000 строк (Rust/Skia WASM)
UI-код ~4 500 строк ~175 000 строк (CLJS + SCSS)
Бэкенд Нет (локальный подход) 32 600 строк + 151 SQL-файл
Соотношение LOC 1× ~11×

OpenPencil примерно в 11 раз меньше — и в этом вся суть. Это не упрощение, а принципиально другая архитектура.

2. Архитектура

OpenPencil: монолитный клиент

┌─────────────────────────────────┐
│         Tauri (native shell)    │
│  ┌───────────────────────────┐  │
│  │  Vue 3 + TypeScript       │  │
│  │  ┌─────────┐ ┌──────────┐│  │
│  │  │  Editor  │ │  Kiwi    ││  │
│  │  │  Store   │ │  Codec   ││  │
│  │  └────┬─────┘ └──────────┘│  │
│  │       │                    │  │
│  │  ┌────▼────────────────┐  │  │
│  │  │  Scene Graph (TS)    │  │  │
│  │  │  Map<string, Node>   │  │  │
│  │  └────┬────────────────┘  │  │
│  │       │                    │  │
│  │  ┌────▼────┐ ┌──────────┐│  │
│  │  │  Skia   │ │  Yoga    ││  │
│  │  │CanvasKit│ │  Layout  ││  │
│  │  │  (WASM) │ │  (WASM)  ││  │
│  │  └─────────┘ └──────────┘│  │
│  └───────────────────────────┘  │
└─────────────────────────────────┘

Всё в одном процессе. Без сервера, без базы данных, без Docker. Граф сцены — плоская Map<string, SceneNode> в TypeScript. Рендеринг вызывает Skia CanvasKit напрямую из TS. Макет — Yoga WASM, вызываемый синхронно.

Penpot: распределённый клиент-сервер

┌───────────────────────────────────────────────────────┐
│                    Docker Compose                      │
│  ┌──────────────┐  ┌─────────────┐  ┌──────────────┐ │
│  │   Frontend    │  │   Backend   │  │   Exporter   │ │
│  │  ClojureScript│  │   Clojure   │  │  (Chromium)  │ │
│  │  shadow-cljs  │  │   JVM       │  │              │ │
│  │  ┌─────────┐ │  │  ┌────────┐ │  └──────────────┘ │
│  │  │render-  │ │  │  │Postgres│ │                    │
│  │  │wasm     │ │  │  │Valkey  │ │  ┌──────────────┐ │
│  │  │(Rust→   │ │  │  │ MinIO  │ │  │   MCP        │ │
│  │  │ Skia    │ │  │  └────────┘ │  │   Server     │ │
│  │  │ WASM)   │ │  │             │  └──────────────┘ │
│  │  └─────────┘ │  │             │                    │
│  └──────────────┘  └─────────────┘                    │
└───────────────────────────────────────────────────────┘

Минимум 5+ сервисов. PostgreSQL для хранения, Redis (Valkey) для pub/sub и кеширования, MinIO для хранения ассетов, JVM-бэкенд, Node.js экспортёр (headless Chromium для серверного рендеринга), плюс ClojureScript фронтенд. Для разработки требуется Docker Compose с настроенной сетью.

Вердикт: архитектура

Однопроцессная архитектура OpenPencil устраняет:

  • Сетевую задержку между фронтендом и бэкендом
  • Накладные расходы на сериализацию/десериализацию на границах сервисов
  • Сложность оркестрации контейнеров
  • Накладные расходы на запросы к базе данных при каждой операции

Архитектура Penpot оптимизирована для многопользовательских серверных развёртываний. OpenPencil оптимизирован для мгновенной локальной производительности.

3. Конвейер рендеринга

OpenPencil: TS → CanvasKit WASM (напрямую)

// renderer.ts — прямые вызовы CanvasKit из TypeScript
renderSceneToCanvas(canvas, graph, pageId) {
  // Итерируем узлы, строим Skia paths/paints, рисуем
  this.fillPaint.setColor(...)
  canvas.drawRRect(rrect, this.fillPaint)
}
  • 1 пересечение границы: TS → WASM (CanvasKit)
  • Граф сцены живёт в JS-куче — без сериализации для рендеринга
  • ~3 200 строк рендерера (разбит на 10 специализированных файлов: scene, overlays, fills, strokes, shapes, effects, rulers, labels)

Penpot: JS (скомпилированный из CLJS) → Rust WASM → Skia

Penpot 2.x включает Rust/Skia WASM рендерер (render-wasm/v1), опционально включаемый через серверные флаги или ?wasm=true. При включении фигуры рендерятся через:

ClojureScript (скомпилированный в JS)
  → декомпозиция в примитивы + бинарная упаковка в линейную память WASM
  → Rust WASM (через Emscripten C FFI)
  → skia-safe (Rust-биндинги Skia)
  → Skia (WebGL)

При отключении (по умолчанию) фигуры рендерятся как SVG DOM-дерево через React/Reagent — каждая фигура является DOM-элементом.

  • 1 пересечение границы (JS → WASM), как и у OpenPencil — но с явными накладными расходами на сериализацию: UUID разбиваются на 4×u32, трансформации на 6×f32, заливки/обводки упаковываются в бинарный формат, базовые свойства группируются в 104-байтную структуру на фигуру
  • Тайловая система рендеринга с областями интереса
  • 11 отдельных поверхностей рендеринга (заливки, обводки, тени и т.д.)
  • Глобальное мутабельное состояние через паттерн unsafe { STATE.as_mut() }
  • 22 000 строк Rust-движка рендеринга

Тайловая система Penpot (TileViewbox, TileTextureCache, TILE_SIZE_MULTIPLIER) предварительно рендерит тайлы вокруг области видимости и кеширует текстуры (до 1024 записей).

OpenPencil перерисовывает всю область видимости каждый кадр, потому что CanvasKit, вызываемый напрямую из TS, достаточно быстр и не нуждается в тайлинге.

Вердикт: рендеринг

Аспект OpenPencil Penpot
Граница JS→WASM Напрямую (TS-объекты) Бинарная упаковка (104-байтная структура)
Модель рендеринга Немедленная/полная перерисовка Тайловое кеширование
Управление поверхностями 1 поверхность 11 поверхностей
Расход памяти Низкий (без кеша тайлов) Высокий (кеш на 1024 тайла)
Сложность кода ~3 200 строк (10 файлов) 22 000 строк
Unsafe-код Нет unsafe глобальное состояние

Когда WASM-рендерер Penpot включён, оба проекта используют Skia через JS→WASM. OpenPencil вызывает CanvasKit напрямую с TS-объектами. Penpot декомпозирует данные ClojureScript в бинарно упакованные структуры, записывает их в линейную память WASM и рендерит через 22 000-строчный Rust-движок. При отключённом WASM (по умолчанию) Penpot рендерит фигуры как SVG DOM-дерево. Для малых и средних документов прямой путь через CanvasKit быстрее. Тайловая система Penpot может выигрывать на очень больших канвасах (100K+ фигур), где видна лишь малая область — но накладные расходы значительны.

4. Граф сцены и модель данных

OpenPencil

// Плоская карта, O(1) поиск
nodes: Map<string, SceneNode>
// 29 типов узлов из Kiwi-схемы Figma
// ~390 полей на NodeChange (совместимо с Figma)
  • TypeScript-интерфейсы со строгой типизацией
  • GUID соответствуют формату Figma sessionID:localID
  • Прямой доступ к свойствам — без слоёв косвенности

Penpot

;; 20+ файлов определений типов в common/src/app/common/types/
;; shapes_builder.cljc, shapes_helpers.cljc
;; Отдельные системы типов для: color, component, container, fills,
;; grid, modifiers, objects_map, page, path и т.д.
  • Данные распределены по common/ (49 600 строк .cljc)
  • Отдельные модули геометрии для flex-макета (~6 файлов), grid-макета (~5 файлов), ограничений, границ, углов, эффектов
  • Валидация схем в рантайме (Malli)
  • Данные должны пересекать границу CLJS→Rust для рендеринга

Вердикт: модель данных

OpenPencil использует проверенную схему Figma (194 определения Kiwi) напрямую в TypeScript — без преобразований. Penpot поддерживает собственную систему типов в Clojure/ClojureScript/Rust, требующую ручной синхронизации между всеми тремя.

5. Движок макетов

OpenPencil: Yoga WASM (314 строк)

import Yoga from 'yoga-layout'
// Прямое сопоставление: поля Figma stack* → свойства Yoga flex
const root = Yoga.Node.create()
root.setFlexDirection(FlexDirection.Row)
root.calculateLayout()
applyYogaLayout(graph, frame, yogaRoot)

314 строк всего. Синхронно, внутри процесса.

Penpot: двойная реализация

  1. ClojureScript (common): flex_layout/ (6 файлов), grid_layout/ (5+ файлов) — собственные реализации
  2. Rust WASM: flex_layout.rs (741 строка), grid_layout.rs (843 строки) — реализовано с нуля

Penpot поддерживает два независимых движка макетов (CLJS и Rust), которые должны давать идентичные результаты.

Вердикт: макет

OpenPencil делегирует проверенной библиотеке (Yoga, используется React Native на миллиардах устройств) в 314 строках. Penpot поддерживает ~3 000+ строк собственного кода макета, дублированного на двух языках.

6. Формат файлов и совместимость с Figma

OpenPencil

  • Нативный бинарный формат Kiwi — та же сериализация, что использует Figma внутри
  • Прямой импорт файлов .fig через извлечённый Kiwi-кодек (2 178 строк схемы + 551 строка кодека)
  • Поддержка вставки из буфера обмена Figma (чтение бинарного Kiwi из буфера обмена)
  • Совместимость на уровне протокола с мультиплеерным протоколом Figma

Penpot

  • ZIP-архив (файлы .penpot), содержащий JSON-манифесты, JSON-данные по файлам, бинарные ассеты и миниатюры (формат v3)
  • SVG используется для рендеринга по умолчанию и экспорта (опциональный WASM-рендерер доступен)
  • Нет нативного импорта .fig
  • Три версии формата (v1 legacy Transit, v2, v3 JSON-in-ZIP) с системой миграции

Вердикт: формат файлов

OpenPencil имеет значительное преимущество — он может читать файлы Figma нативно и даже вставлять данные из буфера обмена Figma. Penpot требует ручного экспорта/импорта и не может открывать файлы .fig.

7. Управление состоянием и отмена

OpenPencil

// 110 строк — паттерн обратных команд
class UndoManager {
  apply(entry: UndoEntry) { entry.forward(); this.undoStack.push(entry) }
  undo() { entry.inverse(); this.redoStack.push(entry) }
}

110 строк. Forward/inverse замыкания, захватывающие минимальное состояние. Поддержка группировки для многоэтапных операций.

Penpot

Управление состоянием использует Potok (Redux-подобная библиотека для ClojureScript atoms). События реализуют UpdateEvent (чистое state→state) или WatchEvent (побочные эффекты через RxJS). Отмена хранит обратные векторы изменений (максимум 50 записей), с транзакциями для группировки быстрых изменений и авто-истечением через 20 секунд.

Вердикт: состояние

Подход OpenPencil проще и с меньшими накладными расходами. Подход Penpot больше подходит для совместной работы (изменения сериализуемы), но ценой сложности.

8. Опыт разработчика

Метрика OpenPencil Penpot
Настройка среды bun install && bun dev Docker Compose + JVM + Node + Rust toolchain
Горячая перезагрузка Vite HMR (~50мс) shadow-cljs (секунды)
Проверка типов TypeScript (строгий) В рантайме (схемы Malli)
Время сборки <5с (Vite) Минуты (запуск JVM + компиляция CLJS + Rust WASM)
Порог первого вклада Низкий (TS/Vue) Высокий (Clojure + Rust + Docker)
Десктоп Tauri v2 (~5 МБ) Н/Д (только браузер)
Пул разработчиков Огромный (TS/Vue) Крошечный (ClojureScript + Rust)

9. Характеристики производительности

Сценарий OpenPencil Penpot
Холодный старт <2с (загрузка WASM) 10с+ (сервер + клиент + WASM)
Задержка операций <1мс (в процессе) 10-50мс (сетевой round-trip)
Кадр рендеринга Прямой вызов Skia CLJS→JS→WASM FFI→Skia
Базовый расход памяти ~50 МБ (вкладка браузера) ~300 МБ+ (JVM + Postgres + Valkey + браузер)
Работа офлайн Полная (локальный подход) Нет (зависимость от сервера)
Рендеринг 10K фигур Один проход, без кеширования Тайловый с 11 поверхностями

10. В чём Penpot лучше

  1. Серверная совместная работа — централизованное многопользовательское редактирование с WebSockets, учётными записями и контролем доступа (OpenPencil использует P2P через Trystero + Yjs — без сервера, но и без контроля доступа или сохранения за пределами сессии)
  2. Экспорт PDF — headless Chromium для серверного PDF-рендеринга (OpenPencil экспортирует SVG, но пока не PDF)
  3. Система плагинов — полный API плагинов с изолированным выполнением
  4. Дизайн-токены — нативная поддержка дизайн-токенов
  5. Макет CSS Grid — собственная реализация (OpenPencil ждёт Yoga Grid)
  6. Самостоятельный хостинг — развёртывание на Docker для команд
  7. Зрелость — годы использования в продакшене, проверенный масштабированием

11. Скриптинг и расширяемость

OpenPencil поставляется с командой eval, предоставляющей Figma-совместимый Plugin API для headless-скриптинга — пакетные операции, автоматизированное тестирование и ИИ-модификации работают без GUI. Кроме того, 90 ИИ-инструментов доступны через встроенный чат, MCP-сервер (stdio + HTTP) и CLI — охватывающие чтение, создание, модификацию, структуру, переменные, векторные пути, анализ (цвета/типографика/отступы/кластеры), сравнение, булевые операции и упорядочивание. Penpot имеет систему плагинов с изолированным выполнением, но без headless-скриптинга или интеграции MCP.

Итоги

Аспект Лидер Почему
Простота архитектуры OpenPencil Один процесс vs 5+ сервисов
Производительность рендеринга OpenPencil Прямой CanvasKit vs SVG DOM (по умолчанию) или бинарно упакованный WASM
Поддерживаемость кода OpenPencil ~26K строк на 1 языке vs 299K на 4+ языках
Совместимость с Figma OpenPencil Нативный Kiwi-кодек vs отсутствие поддержки .fig
Онбординг разработчиков OpenPencil TS/Vue vs Clojure/Rust/Docker
Десктоп OpenPencil Нативный Tauri vs только браузер
Движок макетов OpenPencil Yoga (проверенный) vs собственная двойная реализация
Совместная работа Ничья Penpot: серверная с контролем доступа; OpenPencil: P2P через Trystero + Yjs, без хостинга
Самостоятельный хостинг Penpot Docker-ready vs только десктоп
Зрелость экосистемы Penpot Годы продакшена vs ранняя стадия

OpenPencil архитектурно легче — однопроцессный CanvasKit-рендерер в ~26K строках TypeScript, совместимый с Figma по дизайну. Penpot — полноценная платформа с ~299K строками на Clojure, ClojureScript, Rust и SCSS, плюс парк Docker-сервисов. Оба предлагают совместную работу в реальном времени (с разными архитектурами: P2P vs сервер). Penpot имеет экосистему плагинов и серверный экспорт PDF; OpenPencil имеет Figma-совместимый headless-скриптинг, 90 ИИ/MCP инструментов, экспорт SVG и нативное десктоп-приложение.