Разработка десктоп-приложения на Tauri

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка десктоп-приложения на Tauri
Сложная
~1-2 недели
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Разработка десктоп-приложения на Tauri

Tauri — фреймворк для десктоп-приложений, где бэкенд написан на Rust, а фронтенд — любой веб-стек. В отличие от Electron, Tauri не поставляет собственный Chromium: используется системный WebView (WebKit на macOS/Linux, WebView2 на Windows). Результат — дистрибутив от 4 до 15 МБ против 80+ МБ у Electron.

Архитектура

Frontend (HTML/CSS/JS → любой фреймворк)
        ↕ invoke() / events
Tauri Core (Rust)
        ↕ системные вызовы
    ОС (файловая система, нотификации, трей)

Весь небезопасный код выполняется в Rust. Фронтенд может вызывать только явно экспонированные Rust-команды через invoke.

Создание проекта

# Предварительно: Rust + системные зависимости
# macOS: xcode-select --install
# Windows: Visual Studio Build Tools + WebView2
# Linux: webkit2gtk, libayatana-appindicator

npm create tauri-app@latest
# Выбираем: TypeScript, React, Vite

Структура проекта:

my-app/
├── src/              # React/Vue/Svelte фронтенд
├── src-tauri/
│   ├── src/
│   │   ├── main.rs   # точка входа Rust
│   │   └── lib.rs    # команды и плагины
│   ├── Cargo.toml
│   └── tauri.conf.json
├── package.json
└── vite.config.ts

Rust-команды: основа взаимодействия

// src-tauri/src/lib.rs
use tauri::State;
use std::sync::Mutex;

struct AppState {
    counter: Mutex<i32>,
}

// Простая команда
#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

// Асинхронная команда с состоянием
#[tauri::command]
async fn increment(state: State<'_, AppState>) -> Result<i32, String> {
    let mut counter = state.counter.lock().map_err(|e| e.to_string())?;
    *counter += 1;
    Ok(*counter)
}

// Команда с доступом к файловой системе
#[tauri::command]
async fn read_file(path: String) -> Result<String, String> {
    std::fs::read_to_string(&path).map_err(|e| e.to_string())
}

// Команда с app_handle для работы с окнами
#[tauri::command]
async fn open_child_window(app: tauri::AppHandle) -> Result<(), String> {
    tauri::WebviewWindowBuilder::new(&app, "child", tauri::WebviewUrl::App("child.html".into()))
        .title("Child Window")
        .inner_size(400.0, 300.0)
        .build()
        .map_err(|e| e.to_string())?;
    Ok(())
}

pub fn run() {
    tauri::Builder::default()
        .manage(AppState { counter: Mutex::new(0) })
        .invoke_handler(tauri::generate_handler![greet, increment, read_file, open_child_window])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Вызов Rust-команд из фронтенда

// src/api/tauri.ts
import { invoke } from '@tauri-apps/api/core';

export async function greet(name: string): Promise<string> {
  return invoke('greet', { name });
}

export async function increment(): Promise<number> {
  return invoke('increment');
}

export async function readFile(path: string): Promise<string> {
  return invoke('read_file', { path });
}

// Использование в React компоненте
function App() {
  const [count, setCount] = useState(0);

  const handleIncrement = async () => {
    const newCount = await increment();
    setCount(newCount);
  };

  return <button onClick={handleIncrement}>Count: {count}</button>;
}

Система событий

// Rust → Frontend
use tauri::{Manager, Emitter};

#[tauri::command]
async fn start_long_task(app: tauri::AppHandle) {
    tokio::spawn(async move {
        for i in 0..=100 {
            tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
            app.emit("progress", i).unwrap();
        }
        app.emit("task-complete", "done").unwrap();
    });
}
// Frontend — подписка на события
import { listen } from '@tauri-apps/api/event';

const unlisten = await listen<number>('progress', (event) => {
  setProgress(event.payload);
});

const unlistenComplete = await listen('task-complete', () => {
  setDone(true);
  unlisten();
  unlistenComplete();
});

await invoke('start_long_task');

Плагины экосистемы

Tauri имеет официальные плагины для типичных задач:

# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-fs = "2"
tauri-plugin-dialog = "2"
tauri-plugin-notification = "2"
tauri-plugin-shell = "2"
tauri-plugin-store = "2"
tauri-plugin-updater = "2"
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
// src-tauri/src/lib.rs
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_store::Builder::default().build())
        .invoke_handler(tauri::generate_handler![...])
        .run(tauri::generate_context!())
        .expect("error running app");
}
// Frontend — использование плагина store
import { Store } from '@tauri-apps/plugin-store';

const store = await Store.load('settings.json');
await store.set('theme', 'dark');
await store.save();

const theme = await store.get<string>('theme');

Конфигурация разрешений (Capability система)

В Tauri 2.x доступ к API ограничен через capabilities — нужно явно объявить, что разрешено:

// src-tauri/capabilities/default.json
{
  "identifier": "default",
  "description": "Default capabilities",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "fs:allow-read-text-file",
    "fs:allow-write-text-file",
    "fs:allow-app-read-recursive",
    "dialog:allow-open",
    "dialog:allow-save",
    "notification:allow-notify"
  ]
}

Это значит фронтенд не может обратиться к fs если нет разрешения — даже если API доступно в JS.

Сборка и дистрибуция

# Разработка
npm run tauri dev

# Сборка под текущую платформу
npm run tauri build

# Кросс-компиляция через GitHub Actions
# Нужно запускать build на каждой целевой платформе

tauri build производит:

  • macOS: .app + .dmg
  • Windows: .exe (NSIS) + .msi
  • Linux: .deb + .AppImage + .rpm

Когда выбирать Tauri вместо Electron

Tauri оправдан когда: размер дистрибутива критичен, нужна максимальная производительность нативного кода, команда знает Rust или готова его освоить.

Electron оправдан когда: нужна одинаковая среда выполнения без зависимости от системного WebView, команда чисто JS/TS, приложение активно использует экосистему npm-пакетов в основном процессе.

Разница в размере: Tauri ~8 МБ, Electron ~120 МБ. Разница во времени рендеринга: незначительна для типичных UI-задач. Разница в потреблении памяти: Tauri ~30-60 МБ vs Electron 100-200 МБ при старте.