Хочу рассказать про один из моих любимых Opensource проектов: Tauri. Это среда для создания десктопно-мобильных приложений на JavaScript, но быстрых и легковесных. С опциональными дополнениями на Rust, а через него и на всех других языках.

Достоинства

Поддерживается Линь, Вынь и Дрюнь и всякое Ябло. EXEшник HelloWorld весит 1 мегабайт ( ну 5, если не ужиматься в угол как сирота в барском доме ). В памяти занимает на Win 11 200 Мб. (Из них >90% приходится на системные компоненты, расшаренные с другими программами. Поэтому простые средства измерения покажут 5 Мб). Кто-то считает, что это много. Покажите меньше. Только HelloWorld у нас будет такой: в верхней половине окна играет видео с вэба со звуком, а под ним кнопка закрыть, которая при наведении мыши начинает вращаться, и оба эти компонента рендерятся на GPU.

Это достигается тем, что Tauri не тащит с собой браузер, а использует тот, что уже есть в системе. И в самом деле, зачем? В Windows всегда есть движок от Edge, даже если в говносборке вырезан сам Edge. В Андроиде и Ябле всегда есть есть WebKit. Ну а линуксоидов зависимостями не напугаешь, там требуется пакет GTK-WebView. Поддерживается даже Win7/8, но там нужен пакет совместимости весом ~200Мб. Таким образом получается, что нам встретится всего два движка - Хром и WebKit, и на дворе 2024 год, поэтому разница между ними не такая уж значительная.

Вторая приятная сторона Tauri - это гибкость. Полнофункциональное GUI приложение на нём можно написать как целиком на Rust, без строчки на JS, так и целиком на JS, c ровно одной строчкой на Rust. Поэтому знать Rust для его использования не обязательно совсем. Tauri предоставляет в пространство JS модули API для операций, недоступных из браузера - вроде прямого доступа к файлам и железу.

Зрада! Возможность работать только на JS появилась в Tauri 2, который вышел около года назад. Поэтому в сети до сих пор много ссылок на документацию первой версии, где написано, что это всё невозможно.

По сравнению с в чём-то похожим PyWebView, Tauri не имеет папки с файлами, которую нужно носить с собой или распаковывать при каждом запуске, не злит антивирусы распаковками и не требует для работы открытый порт.

Ну и новичков порадует генератор новых проектов с поддержкой TypeScript, React, Vue, чёрта с рогами и без. Потому что под капотом там сидит Vite. Во время разработки есть Hot Reload.

Начинаем

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

Ставим Rust. Идём на его сайт и качаем утилиту rustup (64 бит) , которая по сути есть инсталлятор Rust. Ставим всё по умолчанию. Под Windows Rust использует компилятор Microsoft, а тот в свою очередь идёт с большой пачкой библиотек, поэтому установка займёт долго и качает много.

Теперь поставим NodeJS ради его утилиты npm. Открываем терминал и набираем winget install OpenJS.NodeJS.LTS Сработает - хорошо. Если winget опять отвалился, качаем NodeJS с его сайта.

Текстовый редактор оставлю на ваше усмотрение. Для VSCode есть экстеншн для Rust (rust-analyzer) и отдельный специально для Tauri, и ещё пригодится Better TOML.

Проверяем. Вводим в консоли cargo -V (большая) потом npm -v (маленькая). Если выводит номера версий - то всё в порядке.

Сам Tauri ставить не надо, он качается в проект.

Создаём проект

Зрада! Даже если вы собираетесь писать на JavaScript, при создании проекта надо выбирать TypeScript. Это потому, что для проекта TypeScript ставится Vite и прочие ништяки, а проект на JavaScript суперминималистичный. Чтобы в TypeScript-проекте начать писать на JavaScript - достаточно переименовать файл из .ts в .js и убрать его из tsconfig.json.

Открываем в PowerShell папку, где у нас лежат поделки, и набираем npm create tauri-app@latest Нам зададут несколько вопросов, везде нужно выбирать "TypeScript" "Vanilla" а остальное по умолчанию. Когда создание закончится, нужно перейти в папку проекта, набрать один раз npm install а потом npm run tauri dev Наш тестовый проект соберётся и запустится! Теперь, не выключая его, откроем в проекте файл index.html, поменяем в нём что нибудь (заголовок в h1 например) и сохраним. Сразу увидим изменения в запущенном приложении. Кстати, по правому клику в приложении доступно меню с отладочными инструментами. Оно есть только в debug сборке.

Давайте пройдёмся по созданному проекту. В корне у нас лежит index.html. Это HTML главного окна приложения. Честно говоря, не знаю, зачем он вынесен сюда, поскольку вся остальная web-часть убрана в папку src. Ещё мы видим надеюсь знакомые вам package.json и папку node_modules - следы жизни npm. В папку dist кладутся промежуточные стадии упаковки, эту папку не нужно бэкапить или класть в git. Но самая мякотка лежит в папке src-tauri.

В ней: cargo.toml - основной файл нашего проекта. В нём надо зайти и прописать название приложения, версию и автора - эти данные пойдут в метадату ЕХЕ-шника. Заодно в разделе dependencies убедитесь, что tauri у вас второй версии, а то были странные прецеденты.
cargo.lock руками трогать не надо, там список фактически используемых пакетов Rust.

Папка target - туда идут результаты компиляции. Это та папка, которую не надо бэкапить или класть в git. Если в корне проекта выполнить команду npm run tauri build то в папке target/release появится финальная версия нашей программы, со всеми ресурсами упакованными внутрь. Мало того, в папке release/bundle будет программа, запакованная в .msi. Причём это умный инсталлятор, который проверит и предложит скачать все зависимости.

Папка icons содержит иконку нашей программы в вариантах под все платформы. К счастью, это безобразие нам не нужно делать руками. Нам нужна одна иконка в формате PNG размером 1024 пикселя с прозрачностями в интересных местах. Затем в корне проекта вызываем npm run tauri icon /path/to/app-icon.png и все виды иконок появятся сами.

В src-tauri/src лежат непосредственно исходники на Расте. Их сегодня трогать почти не будем. Но можно заглянуть и поразиться минимальности. Изменения исходников на Расте не подхватываются на лету, приложение надо перезапускать.

Настройка Tauri

И наконец файл tauri.conf.json, и capabilities - часть его. Это очень важный конфиг самого Tauri. Открываем.

productname, version, identifier используются при сборке под мобильники. identifier должен быть уникальным в мире, поэтому проявите фантазию.

app - withGlobalTauri это костыль, включённый по умолчанию. Давайте напишем туда false и будет сразу делать как надо (ниже покажу).

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

Остальное сейчас не важно.

Давайте покодим!

Не буду учить кодить на JavaScript. Вместо этого давайте покажу, как обойтись без бэкэнда на расте, с одним JS. Для этого нам понадобятся так называемые "плагины", они дают нам доступ к системе.

Открывам src/main.ts. Один плагин тут уже есть: api/core. Он позволяет передавать данные на лету между бэком на расте и фронтом. Можно, конечно, было бы и сокет открыть для этого дела и любой другой способ, но через плагин намного проще и быстрее. Посмотрим, что происходит. Из плагина импортируем функцию invoke и вызываем её с аргументом "greet". Что это за greet? Это функция, объявленная в файле src-tauri/lib.rs, а макрос #[tauri::command] делает её доступной из JS.

Зрада! Если вы всё таки кодите на Расте, то помните, что при работе с Tauri нужно по максимуму пользоваться npm, а cargo вызывать только для самых Растовых операций вроде cargo add. Иначе временами вылезают эфемерные баги с неопределённым положением в пространстве. В документации есть целый раздел об этом.

Давайте вместо функции на Расте, прочитаем текст из файла. Создадим текстовый файл, у меня это будет E:/name.txt. За работу с файлами у нас отвечает плагин fs.

В отличие от плагина core, который есть всегда, большинство плагинов нужно установить и потом ещё включить. Сначала в корне проекта набираем npm run tauri add fs а потом в capabilities/default.json делаем

"permissions": [
    "core:default",
    "shell:allow-open",
    "fs:default",
    {
      "identifier": "fs:allow-open",
      "allow": [{ "path": "**" }]
    },
    {
      "identifier": "fs:allow-read",
      "allow": [{ "path": "**" }]
    }      
  ]

Мы разрешили себе чтение из любого файла в системе. Лучше, конечно, по возможности ограничивать пути. Всё, теперь в main.ts можно изменить функцию greet на чтение из файла.

import { open } from "@tauri-apps/plugin-fs";
async function greet() {
  if (greetMsgEl && greetInputEl) {
    // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
    const file = await open("E:/name.txt" );
    const buf = new Uint8Array(20);
    const numberOfBytesRead = await file.read(buf); // 11 bytes
    const text = new TextDecoder().decode(buf);  // "hello world"
    await file.close();
    greetMsgEl.textContent = "Да здравствует товарищ" + text;
  }
}

Ну и всё. Запускаем опять npm run tauri dev если выключили. Теперь по нажатию кнопки должно приветствоваться имя из файла.

Комментарии (30)


  1. MountainGoat Автор
    12.10.2024 13:22

    Я считаю, что Tauri может заменить не только Electron, но в перспективе и Flutter тоже.


    1. SserjIrk
      12.10.2024 13:22

      Если говорить о Flutter то разница с первых строк:

      "... . В памяти занимает на Win 11 200 Мб. Кто-то считает, что это много. Покажите меньше. .."

      У Flutter вместе с движком демка собирается в 23Мб, в памяти занимает 30Мб.

      Старая добрая JavaFX (OpenJFX) собранная через GraalVM в нативный exe получается 25 Мб, в памяти 28.

      Добавить видео в обе эти вещи легко довесив 10-15 МБ обвязок над облегченным FFmpeg.


      1. MountainGoat Автор
        12.10.2024 13:22

        Не могу проверить. Ни на какой странице с демками Flutter я не нашёл готового EXE, а когда попробовал собрать сам - там что-то править в коде надо и т.д.

        Ещё большой вопрос, как мерять. Task Manager и для Tauri показывает 3 мегабайта. Но извините, у меня там один массив больше.


        1. SserjIrk
          12.10.2024 13:22

          Если действительно интересно результат двух команд в терминале, без открытия редактора:

          flutter create . --org ru.sserjirk --project-name testnative --platforms windows

          flutter build windows

          Можете взять тут: https://disk.yandex.ru/d/eDCdcl-P4UTIHw


          1. MountainGoat Автор
            12.10.2024 13:22

            Спасибо, сравню на днях.

            Я выложил демку, которая получается в этой статье. Пароль "habr"


        1. Octabun
          12.10.2024 13:22

          На Flutter ничего править в коде не надо, даже не представляю как можно на такое выйти. Но это не важно. Важно что вы сравниваете несравнимое.

          Flutter - чисто нативное приложение и рисует своими силами. Tauri чисто Web и рисует силами чужого браузера. Так что сравнивать надо когда во Flutter приложение вставлен Web View, и если при этом Flutter потребит меньше ресурсов, то он лучше. По ресурсам.


          1. Vedomir
            12.10.2024 13:22

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


  1. MountainGoat Автор
    12.10.2024 13:22

    Про что б ещё написать? Два способа написать приложение Tauri на одном Расте без JS (но с HTML)? Или как в эту каракатицу встроить ещё и Питон?


    1. Mingun
      12.10.2024 13:22

      Да, статься про написание на расте было бы замечательно. Еще может быть интересно преобразование существующего SPA-приложения. У меня даже идея появилась -- собрать https://ide.kaitai.io/devel/ в такое приложение. Но наверное там побольше работы, чем написание простых врапперов.


    1. iskateli
      12.10.2024 13:22

      Что-нибудь табличное можете пожалуйста продемонстрировать? Насколько удобно будет работать с таблицей на голом расте или через js например, да и производительность хорошо видно на больших табличках


      1. CaptGg
        12.10.2024 13:22

        Tauri - это просто удобная обертка над Microsoft Edge WebView2 (если в Windows). Производительность такая же как в самом Edge, так что проверить легко в самом браузере.

        А удобство работы с таблицами из Rust зависит от того, как вы реализуете взаимодействие Rust и JavaScript. Tauri дает удобный интерфейс для реализации этого взаимодействия, но функции пишете вы сами. Какие типы данных передаются и как обрабатываются на обоих концах - решаете вы сами в своем коде.

        Можете хоть прямо из Rust строить HTML. А можете реализовать в JS функцию рисующую таблицу из массива данных переданного Rust, что более оптимально.


        1. MountainGoat Автор
          12.10.2024 13:22

          Оптимально как раз строить таблицу в Rust. Потому что можно передавать только те поля, которые видны. Но вот красиво прокручиваться с инерционной прокруткой она не будет.


          1. CaptGg
            12.10.2024 13:22

            Одно другому не мешает, опять же это вопрос реализации функций обмена данными между Rust и JavaScript. Если это просто статическая таблица, то отдавать HTML из Rust будет вполне удобно.

            Но если это часть интерактивного пользовательского интерфейса или сама таблица интерактивна, то реализовать её проще и быстрее на JavaScript, обмениваясь с Rust только необходимыми данными.


    1. Vedomir
      12.10.2024 13:22

      Больше Rust интересней. Зачем тут еще Python не очень понятно - JS/TS допустим необходимое зло для написания интерфейса на веб и тут уже вырисовывается один фронт и на веб-мобилки-десктоп, а Python язык примерно того же высокого уровня и я не пытаюсь сказать что он плохой, он тоже хороший, но в нем нет необходимости и его в такой проект актуально добавлять примерно на одном уровне с массой других хороших язков (Go?C#?Kotlin?).


      1. MountainGoat Автор
        12.10.2024 13:22

        Зачем тут еще Python

        Я уже несколько раз натыкался, когда для какой-то цели на Python есть замечательная библиотека, а на Rust нету/сырая. Если это не центральная вещь для приложения, а опциональная хотелка, то проще вклеить в EXE шник ещё и Питон, чем разрабатывать с нуля.

        Или ещё бывает, что у какого-то сервиса под Питон есть официальный API а под Rust - фигуёки. И тут либо реверсить их протокол, заодно не имея возможности спросить на форуме про проблемы; либо же опять таки встраивать Питон.

        Благо для юзера снаружи это совершенно незаметно.


        1. Vedomir
          12.10.2024 13:22

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


  1. ImagineTables
    12.10.2024 13:22

    В памяти занимает на Win 11 200 Мб. Кто-то считает, что это много. Покажите меньше. Только HelloWorld у нас будет такой

    Это многовато. В реальном проекте с расходом памяти менее 100 мегабайт (трудно сказать точно, поскольку дело происходило в чужом адресном пространстве — я смотрел на working set / private bytes чужого процесса до и после встраивания) я имел не просто скриптовый язык (диалект экмы + элементы jQuery), но и полноценную разметку со стилизацией и анимациями (в смысле, в проекте активно использовались эффекты и анимации, а не просто поддерживались движком). Бинарники были менее 5 метров, ещё столько же на ресурсы.

    Правда, я замерял под Win7, хз, сколько оно скушало бы под 11.


  1. Astroscope
    12.10.2024 13:22

    Оффтопик

    В Windows всегда есть движок от Edge, даже если в говносборке вырезан сам Edge.

    Почему, зачем, с какой целью неуемные Васяны вырезают Edge? Чтобы что? Чтобы поставить ровно то же самое, только в незначительных мелочах хуже, но от Google? Нет, я ничего не имею против околотехнического творчества Васянов самого по себе, сделать говносборку с нескучными обоями вполне себе хобби (впрочем, Васянов и говносборок много, а БолгенОС - одна, не имеющая аналогов, поэтому достижение, если сравнивать с настоящими мастерами, так себе), но зачем дурь пропагандировать, без сколь-нибудь полного понимания вырезая "лишнее" - не только Edge, но и другие "плохие" компоненты? Вопрос, пожалуй, скорее риторический.


  1. JakErdy
    12.10.2024 13:22

    Имхо. Как и все поделки на расте, эта выглядит так же шапкозакидательно как и всё остальное "написаное на раст btw". На мой взгляд у tauri слишком много минусов чтобы делать на нём сколь нибудь серьёзный проект.

    1. Отсутствие гарантии наличия web view на компе у конечного пользователя

    2. Отсутствие гарантии что через пару лет сам microsoft не решит выпилить webview из дефолтной поставки, или что будет продолжать его обновлять

    3. Зоопарк браузерных движков на разных платформах, с разным подмножеством поддерживаемых фичь

    4. Rust. Я уж лучше буду на плюсах писать чем на этом творении великого сумрачного гения. Сколько там людей на рынке, кто согласиться писать на расте нативные расширения не связанные с криптой, и прочим модным молодёжным?

    Короче говоря, если это не пет проект, и жизненный цикл продукта больше чем 5 лет, electron будет сильно лучше и надёжнее. Плюс ко всему старые билды будут запускаться, и что самое главное работать, вне зависимости от того что там снаружи.


    1. McHack
      12.10.2024 13:22

      1. В конфиге Tauri можно указать, чтобы он чекал наличие WebView. Если его нет, то программа предложит его докачать. Делается одной строчкой в конфиге

      2. Смотрим первый пункт

      3. На то и существуют стандарты ES и сама Javascript Foundation, чтобы регулировать весь этот зоопарк. Уже давно не нулевые, где каждый делал что хотел. Времена jQuery уже давно прошли, добро пожаловать в современный вэб

      4. Дело вкуса, тут не поспоришь

      WebView уже на вряд-ли покинет стандартный набор библиотек любой ОС. Это неотъемлемая часть взаимодействия с системой. У Майков даже системные вещи уже через WebView работают, если что на 11 Винде новая нижняя панель на Реакте написана (тут могу ошибаться)


  1. Flux
    12.10.2024 13:22

    для создания десктопно-мобильных приложений на JavaScript

    Нет, не попробуем. Дальше можно не читать.


  1. CrashLogger
    12.10.2024 13:22

    На что только люди не идут, лишь бы не учить нормальный язык вместо JS )


    1. abagnale
      12.10.2024 13:22

      НИ!


    1. Vedomir
      12.10.2024 13:22

      Ну тут как посмотреть. Есть идея некого (пет)проекта с десктопно-мобильным приложением. Понятно что скорее всего вообще не займусь,а если и займусь то сделаю что-то минимальное, но от платформы хочется полноценной поддержки всех основных десктопных и мобильных платформ включая Linux, веб тоже хорошо бы, и как обязательное требование наличие качественного визуального редактора текста. С/С++ как-то совсем не хочется.

      Что остается? Flutter, Electron/React Native. Теперь еще Tauri.

      Является ли Dart нормальным языком по сравнению с TypeScript?

      В свое время много писал на С#, но например MAUI и Blazor в WebView не поддерживают Linux, а в Avalonia нет визуального редактора текста.

      Wails не поддерживает мобильные платформы и там тоже фронт на TS.


      1. MountainGoat Автор
        12.10.2024 13:22

        У меня аргумент проще. Сквозь UI на JavaScript прокручивается на 2 порядка больше бабла чем через все остальные UI вместе взятые. Угадайте, где всё максимально отлажено, отполировано и задокументировано?


        1. Vedomir
          12.10.2024 13:22

          Множно сказать красивее - самая большая экосистема.


        1. Flux
          12.10.2024 13:22

          всё максимально отлажено, отполировано и задокументировано

          Настолько отполировано что для функции is_number нужна отдельная библиотека?


          1. MountainGoat Автор
            12.10.2024 13:22

            Это о чём речь?


  1. JRJ2309
    12.10.2024 13:22

    Не особо люблю tauri, да и тыкал его всего раз на релизе, но статья написана оч классно, легко и интересно) спасибо автору, появился повод поиграться с платформой на досуге


  1. Vedomir
    12.10.2024 13:22

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