studio

Десктопный инструмент для мудбордов, нарезок и сессий на общем ядре (Rust + Tauri). Там, где важны доступ к файлам, офлайн-работа и скорость нативного приложения. Один репозиторий, общее ядро, отдельные приложения.

studio
TL;DR

Десктопный инструмент разработчика для работы с мудбордами, нарезками и сессиями, собранный на Rust + Tauri. Быстрый доступ к файлам и работа офлайн, нативная скорость вместо вкладки браузера, и при этом одно репо и общее ядро вместо отдельного кода на каждую платформу.

Введение

studio - это десктопный инструмент разработчика, который обслуживает работу с мудбордами, нарезками и сессиями - вещи, при которых важен постоянный, быстрый доступ к файлам на диске. Этот кейс посвящён тому, как построить такой инструмент нативно, не умножая при этом код на каждую операционную систему.

Предпосылка была двусторонней. С одной стороны, инструмент должен ощущаться как нативная программа: файлы под рукой, работа без сети, плавность даже при большой сессии. С другой - он должен остаться одним репозиторием и одним ядром, а не тремя отдельными приложениями, которые потом нужно поддерживать втройне.

Чего не даёт браузер

Работа с мудбордами и нарезками - это постоянное обращение к дискам: сотни файлов, каталоги проектов, просмотры, которые должны появляться мгновенно. Браузер держит всё это за стеной песочницы. Каждый доступ к файлу - это диалог, отсутствие сети - это отсутствие приложения, а при большей сессии интерфейс начинает захлёбываться.

Мы хотели инструмент, который имеет файлы под рукой как нативная программа, работает без сети и не замедляется при большой сессии. Но без ловушки, в которую легко попасть при нативном написании: отдельного кода на Windows, macOS и Linux, который потом расходится между платформами и умножает работу при каждом изменении.

Почему Tauri, а не Electron

Tauri переворачивает компоновку, знакомую по Electron. Интерфейс вы пишете один раз, вебом, но не возите с собой весь браузер - окно использует системный движок рендеринга, а вся более тяжёлая работа, доступ к файлам и логика сидят в ядре на Rust. Результат - бинарник, измеряемый в мегабайтах, а не в сотнях мегабайт, и реальный доступ к системе, которого обёрнутая страница никогда не имела.

Разница не косметическая. Electron доставляет свою собственную копию движка браузера с каждым приложением, поэтому каждый инструмент платит за тот же Chromium заново. Tauri использует то, что у системы уже есть, и добавляет лишь тонкий собственный слой. Для инструмента, который должен быть быстрым и лёгким, это разница между работает и работает мгновенно.

Tauri vs Electron

СвойствоTauriElectron
Движок рендерингасистемныйсобственная копия Chromium
Размер бинарникамегабайтысотни мегабайт
Ядро логикиRustNode.js
Доступ к системенативный, через командычерез слой браузера

Веб рисует, Rust делает

Разделение чистое, и именно оно держит всю архитектуру в узде: веб рисует, Rust делает. Виды мудбордов и нарезок написаны один раз, вебом, а операции над файлами, индексация и всё, что должно быть быстрым и офлайн, проходит через команды Tauri в ядро, которое ничего не знает о внешнем виде.

Ядро на Rust - это самостоятельная библиотека: чтение файлов, индексация, модель сессии. Они не зависят от того, кто их рисует, поэтому ту же логику можно тестировать без интерфейса и выставлять тем же контрактом на каждой платформе. Вид - это тонкий слой сверху, а не место, в котором живёт знание о проекте.

commands.rs · rust
#[tauri::command]
fn open_moodboard(path: String) -> Result<Moodboard, String> {
    Moodboard::load(&path).map_err(|err| err.to_string())
}
1
репо, общее ядро на Rust
3
платформы из одного источника
100%
функций доступны офлайн

Граница, которую мы стережём

У чистого разделения есть ещё одно преимущество: есть только одно место, в котором нужно стеречь ошибки всерьёз. Внутри ядра мы доверяем своим типам - если сессия загружена, её модель корректна. Но путь к файлу, приходящий из вида, - это вход извне. Он может не существовать, может указывать на повреждённый файл, может быть остатком от перенесённого проекта.

Поэтому валидация сидит ровно на границе - на команде Tauri - а не размазана по всему ядру на всякий случай. Там, где веб встречается с Rust, ошибка превращается в читаемое сообщение для пользователя; глубже уже не нужно проверять то же самое второй раз.

i
Примечание

Граница между вебом и ядром - это единственное место, где мы стережём ошибки всерьёз. Внутри ядра мы доверяем своим типам, но путь к файлу из вида - это вход извне - и только здесь, на команде Tauri, он превращается в читаемое сообщение, вместо того чтобы опрокинуть приложение глубже.

1
Ядро на Rust

чтение файлов, индексация и модель сессии как библиотека, независимая от интерфейса.

2
Вебовый интерфейс

виды мудбордов и нарезок написаны один раз, связаны с ядром через команды Tauri.

3
Работа офлайн по замыслу

данные и файлы хранятся локально, sync - это опция, а не условие запуска.

4
Один проход на три платформы

build из одного источника на Windows, macOS и Linux, без отдельных веток кода.

Каков итоговый результат

Инструмент стартует быстро, имеет файлы под рукой и не нуждается в сети, чтобы работать - и при этом не умножает код на каждую систему. Одно репо, одно ядро на Rust, тонкий слой вида сверху и отдельные приложения на выходе, собранные из одного источника.

Для человека, который им пользуется, это значит, что инструмент ведёт себя как нативная программа, а не как страница, притворяющаяся приложением: файлы вы указываете прямо с диска, работа идёт дальше без сети, а интерфейс не захлёбывается при большой сессии. Для поддержки - что новая функция, добавленная в ядре, попадает на все три платформы сразу, вместо того чтобы быть написанной и сломанной три раза по отдельности.

Файлы под рукой как в нативной программе, одно ядро на Rust под спудом, три платформы из одного источника.

Больше проектов

Другие работы из той же категории - посмотрите, как мы решаем похожие задачи.

Есть похожий проект?

Напишите нам - смета бесплатна и приходит в течение часа.