Значительное улучшение инструментария: эмуляторы для мобильных устройств, магический Hot-Reloading, интерактивный CLI, и многое другое!


Сегодня мы выпускаем Dioxus 0.6!

Dioxus — это фреймворк для создания фуллстек, десктопных и мобильных приложений с единой кодовой базой. Наша цель — создать «Flutter, но лучше». Dioxus ориентирован на полноценную поддержку фуллстек веб-разработки, типобезопасное взаимодействие между сервером и клиентом, а также высокую производительность.

С этим обновлением мы сосредоточились на упрощении использования Dioxus, улучшении DX и исправлении багов.

Главной особенностью этого релиза является полная переработка Dioxus CLI:

  • dx serve для мобильных устройств: Запускайте свое приложение на Android и iOS эмуляторах и устройствах.

  • Магический Hot-Reloading: Hot-Reloading форматированных строк, свойств и вложенных rsx!{} .

  • Интерактивный CLI: Полная переработка интерфейса Dioxus CLI с новым, интерактивным UX, вдохновленным Astro.

  • Встроенные Stack Traces: Перехват паник и логов из WASM прямо в терминал.

  • Server Functions для нативных проектов: Встроенный Server RPC для Desktop и Mobile приложений.

Мы также улучшили DX по всему фреймворку, исправив давние баги и улучшив инструменты разработки.

  • Всплывающие уведомления и загрузочные экраны: Новые всплывающие уведомления и экраны загрузки для веб-приложений в процессе разработки.

  • Улучшенное автодополнение: Значительные улучшения автодополнения для RSX.

  • Стабилизация asset!: Стабилизация интеграции системы управления ассетами для нативных приложений.

  • Стриминг HTML: Поддержка потоковой передачи Suspence и Error ограничений (boundaries) с сервера на клиент.

  • SSG и ISG: Поддержка для Static Site Generation и Incremental Static Regeneration.

  • Обработка ошибок при помощи ?: Использование оператора ? для обработки ошибок в обработчиках событий, тасках и компонентах.

  • Мета элементы: Новые Head, Title, Meta и Link элементы для управления документными аттрибутами.

  • Синхронный prevent_default: Обработка событий синхронно на всех платформах.

  • Обработчик событий onresize: Отслеживание размера элемента без использования IntersectionObserver.

  • Обработчик событий onvisible: Отслеживание видимости элемента без IntersectionObserver.

  • WGPU интеграция: Рендеринг Dioxus поверх WGPU-окон и дочерних окон.

  • dx bundle для Web, iOS и Android: Полная поддержка dx bundle для всех платформ.

  • json режим: Генерация CLI-сообщений в формате JSON для интеграции с инструментами и CI/CD.

  • Новые шаблоны: Три новых стартовых шаблона для кроссплатформенных приложений.

  • Nightly туториалы и гайды: Обновленные учебники и руководства для Dioxus 0.6 и последующих версий.

  • Прототип бинарного патчинга: Прототип нового hot-reloading движка, написанного на чистом Rust’е.


Об этом релизе

Dioxus 0.6 — наш самый крупный релиз на сегодняшний день: более 350 замерженных пул-реквестов, и сотни закрытых issue. Мы выпустили версию 0.6 с несколькими целями:

  • Значительно улучшить качество процесса hot-reloading’а, автозаполнения и упаковки ассетов.

  • Сделать интерфейс Dioxus CLI более надежным и удобным в использовании.

  • Интегрировать инструменты для мобильных устройств в интерфейс Dioxus CLI для полноценной поддержки мобильных платформ.

Поскольку этот пост довольно длинный, мы подготовили короткое видео о новых фичах, исправленными ошибками и обзором всего, что теперь можно делать с Dioxus:

Интерактивные инструменты командной строки

Dioxus 0.6 поставляется с полностью обновленным интерфейсом командной строки (CLI)! Мы переписали CLI с нуля, чтобы добавить множество новых функций и улучшить его стабильность:

Новый CLI включает индикаторы выполнения в реальном времени, анимации, интерактивную систему фильтров, возможность изменять уровни логирования на лету и многое другое.

Переписывание интерфейса командной строки (CLI) заняло более половины этого цикла выпуска. Мы прошли через несколько итераций дизайна и решили множество ошибок. Вот некоторые ключевые моменты:

  • Вы можете вручную пересобрать свое приложение, нажав r.

  • Можно на лету переключать уровень логирования вывода CLI и даже просматривать внутренние логи Cargo.

  • Мы выводим все внутренние логи CLI, чтобы вы могли отлаживать любые проблемы.

  • Мы перехватываем логи и паники из WASM.

  • Концепция outdir была удалена; теперь для всех выходных данных используется target/dx.

  • Встроенная поддержка эмуляторов iOS и Android.

Вы можете установить новый интерфейс командной строки с помощью cargo binstall, выполнив команду cargo binstall dioxus-cli@0.6.0 --force .


Android и iOS поддержка в dx serve

С выходом нового релиза, Dioxus CLI поддерживает dx serve --platform ios/android прямо из коробки! ?

Хотя поддержка мобильных платформ в Dioxus существовала и раньше, инструменты Rust для мобильной разработки были крайне нестабильны. Пользователи часто сталкивались с проблемами при работе с такими инструментами, как cargo-mobile и cargo-mobile2. Эти инструменты, хоть и полезные, имеют другой архитектурный подход, который не совсем подходит для Dioxus.

В этом выпуске мы полностью переписали систему инструментов для мобильных устройств. Теперь вы можете за несколько секунд перейти от dx new к dx serve --platform ios.

Android и iOS эмуляторы поддерживают все те же функции, что и Desktop: hot-reloading, быструю пересборку, упаковку ассетов, логирование и многое другое. Dioxus — единственный фреймворк на Rust, который поддерживает использование main.rs для мобильных устройств. До этого ни один инструмент не предлагал единый main.rs для всех платформ.

Наша встроенная поддержка мобильных устройств не требует дополнительных настроек, ручной конфигурации Gradle, Java, Cocoapods или использования сторонних инструментов. Если у вас уже установлены Android NDK или iOS Simulator, вы всего в 30 секундах от создания готового к продакшену мобильного приложения, полностью написанного на Rust.

Самое простое мобильное приложение Dioxus 0.6 получается крошечным:

use dioxus::prelude::*;

fn main() {
    dioxus::launch(|| rsx! { "hello dioxus! ?" });
}

Особенно это заметно по сравнению с версией v0.5, где требовалось переносить приложение в cdylib и вручную настраивать слой привязки:

// no main allowed! - must expose a `start_app` function
#[no_mangle]
#[inline(never)]
#[cfg(any(target_os = "android", target_os = "ios"))]
pub extern "C" fn start_app() {
    #[cfg(target_os = "android")]
    {
        tao::android_binding!(
            com_dioxuslabs,
            app_name,
            WryActivity,
            wry::android_setup,
            _start_app
        );
        wry::android_binding!(com_dioxuslabs, app_name);
    }

    // need to manually catch panics!
    #[cfg(target_os = "ios")]
    stop_unwind(|| main())
}

#[cfg(any(target_os = "android", target_os = "ios"))]
fn stop_unwind<F: FnOnce() -> T, T>(f: F) -> T {
    match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
        Ok(t) => t,
        Err(err) => {
            eprintln!("attempt to unwind out of `rust` with err: {:?}", err);
            std::process::abort()
        }
    }
}

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

Если вы заинтересованы в том, чтобы помочь нам развивать поддержку мобильных устройств, присоединяйтесь к нам в Discord (English).


Полностью обновленный Hot-Reloading

Мы внедрили масштабные улучшения в hot-reloading engine, используемый в Dioxus. Наша внутренняя цель заключалась в том, чтобы разрабатывать Dioxus Docsite без необходимости пересобирать весь проект.

Для этого нам пришлось добавить поддержку ряда новых функций для hot-reloading engine:

  • Hot-reload отформатированных строк

  • Hot-reload вложенных rsx блоков

  • Hot-reload свойств компонентов и простых Rust выражений

  • Hot-reload для мобильных платформ и связанных с ними ассетов

Новый hot-reloading engine практически кажется магией — вы можете быстро вносить изменения в новые дизайны и даже изменять простой код на Rust без ожидания полной пересборки проекта:

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

#[component]
fn Counter(count: i32, class_ext: String) -> Element {
    rsx! {
        // Instantly hot-reload these formatted strings
        button { class: "btn-{class_ext}", "Count {count}" }

        // Even hot-reload formatted strings as props on components
        Component { text: "btn-{class_exit}" }
    }
}

Те же инструменты, которые обеспечивают перезагрузку свойств компонентов, работают с любыми Rust литералами! Вы можете выполнять hot-reloading для чисел, строк и boolean типов в границах свойств компонентов.

fn LoopIt() -> Element {
    rsx! {
        // Change either prop without causing a full rebuild
        Link {
            to: "google.com",
            enabled: false
        }
    }
}

Новый движок hot-reloading’а также поддерживает hot-reloading вложенных rsx. Содержимое циклов for, условных операторов if и тел компонентов теперь участвует в hot-reloading’е:

fn LoopIt() -> Element {
    rsx! {
        for x in 0..10 {
            // modifying the body of this loop is hot-reloadable!
            li { "{x}" }
        }

        Counter {
            // component children also get hot-reloaded
            div { "These div contents get hot-reloaded too!" }
        }
    }
}

Теперь вы можете перемещать и клонировать выражения Rust между контекстами, позволяя переиспользовать компоненты и отформатированные строки в свойствах элементов без полной пересборки проекта.

fn LoopIt() -> Element {
    rsx! {
        // If we start with this formatted text
        "Thing1 {a}"

        // we can add this formatted text on the fly
        "Thing2 {a}"
    }
}

Эти изменения поддерживаются на всех платформах: веб, настольных и мобильных приложениях.

Теперь вы можете выполнять hot-reloading RSX и ассетов в приложениях для iOS и Android, к дополнению к классическим веб и десктопным приложениям.

Новая система hot-reloading’а кажется настоящей магией — мы приглашаем вас попробовать её в деле!


Полностью переработанное автодополнение

Еще одно крупное улучшение в Dioxus 0.6 — значительно улучшенное автодополнение для rsx! {}. Наша старая реализация rsx! {} страдала от слабой интеграции с такими инструментами, как rust-analyzer, который предоставляет language-server интеграцию для вашего кода. Если входные данные макроса не могли быть корректно спаршеными, мы не генерировали никаких токенов, что мешало rust-analyzer предлагать варианты автодополнения.

Работа над исправлением этой проблемы была огромной. Библиотеки парсинга макросов, такие как syn, не предоставляет хороших возможностей для "частичного разбора" кода на Rust, что необходимо для реализации улучшенной обработки ошибок и автодополнения. Нам пришлось переписать всю внутреннюю часть rsx! {}, чтобы поддерживать частичный парсинг rsx! {}, но, наконец-то, в версии 0.6 мы добились превосходного автозаполнения. Теперь мы можем не только автодополнять код на Rust в местах атрибутов, но при помощью некоторых трюков мы можем также автоматически вставлять соответствующие фигурные скобки рядом с именами элементов:

Теперь автодополнение стало намного удобнее: все атрибуты, элементы, компоненты и встроенный код Rust извлекли пользу из обновленного интерфейса. Все выражения на Rust участвуют в корректном автодополнении rust-analyzer’а, и мы даже можем выдавать предупреждения при некорректном вводе в rsx!{} вместо того, чтобы выбрасывать панику.


Вложенные WASM stacktraces и интеграция tracing

Вместе с переработкой Dioxus CLI мы внедрили интеграцию tracing крейта для приложений WASM, которая перехватывает паники и логи, отправляя их в dx в вашем терминале. Когда вы собираете приложение с отладочными символами, stack traces напрямую интегрируются с вашим редактором, позволяя мгновенно переходить к проблемным файлам прямо из терминала.

Благодаря этой интеграции логирование в fullstack приложениях стало намного удобнее: теперь отображаются коды состояния, загруженные ассеты и другая полезная информация во время разработки. С переключаемыми режимами детализации логов вы можете просматривать внутренние логи самой CLI, что облегчает отладку и помогает понять, что именно делает dx при сборке вашего приложения. Просто нажмите v, чтобы включить "verbose” режим, и t, чтобы активировать “trace” режим для более информативных логов:


Всплывающие уведомления и загрузочные экраны

В рамках переработки нашей CLI мы стремились предоставить более удобную обратную связь для разработчиков при сборке веб-приложений. В Dioxus 0.6 теперь отображаются всплывающие уведомления и загрузочные экраны для веб-приложений в режиме разработки.

Теперь, когда ваше приложение собирается, Dioxus будет отображать экран загрузки с текущим прогрессом сборки:

Кроме того, после пересборки приложения вы получите всплывающее уведомление (toast) с указанием статуса сборки:


Fullstack Desktop и Mobile

Кроме того, мы должным образом интегрировали server functions с нативными приложениями. Теперь server functions работают "из коробки" при разработке для десктопных и мобильных приложений:

По умолчанию, во время разработки приложения мы устанавливаем endpoint для server functions на localhost, поэтому в продакшене необходимо убедиться, что функции указывают на развернутый сервер:

fn main() {
    #[cfg(feature = "production")]
    server_fn::client::set_server_url("app.endpoint.com");

    dioxus::launch(app)
}

Стабилизация Manganis asset!() системы

Мы представили нашу новую систему управления ассетами Manganis в альфа-версии с выпуском 0.5. В Dioxus 0.6 система ассетов была стабилизирована, а также исправлены несколько багов и проблемы с производительностью.

Вы можете опробовать новую систему ресурсов на основе новой системы компоновщика ассетов, добавив asset! в любом месте вашего кода. Ассеты будет автоматически оптимизированы и упакованы для всех платформ:

rsx! {
    img { src: asset!("/assets/image.png") }
}

Manganis — это важный шаг к поддержке ассетов на разных платформах, особенно через зависимости. Ранее, если библиотека хотела экспортировать ресурс, например изображение или таблицу стилей, ваше приложение должно было вручную добавлять эти ресурсы в папку assets. Это становилось сложным и запутанным, особенно когда библиотеки генерировали CSS: многие классы дублировались и даже могли конфликтовать друг с другом.

Теперь весь CSS, собранный с помощью макроса asset!(), обрабатывается через наш конвейер сборки, получая преимущества минимизации и удаления дубликатов. Библиотеки могут включать свои таблицы стилей, изображения и компоненты, и вы можете быть уверены, что все эти ресурсы будут включены в сборку вашего приложения:

fn app() -> Element {
    rsx! {
        cool_icons::SomeCoolImage {}
    }
}

// in a distant library....
mod cool_icons {
    pub fn SomeCoolImage() -> Element {
        rsx! {
            img { src: asset!("/assets/some_cool_image.png") }
        }
    }
}

Даже лучше: такие ассеты, как изображения, автоматически оптимизируются для создания миниатюр и более эффективных форматов. Это может значительно сократить объем данных на вашем сайте — форматы AVIF и WebP способны уменьшить размер файлов до 90%. Забавный факт: такие платформы, как Vercel, предлагают платные услуги по оптимизации изображений, тогда как Manganis делает это для вас бесплатно, на этапе сборки!

Кроме того, Manganis автоматически хэширует изображения и изменяет сгенерированные имена ассетов, что обеспечивает лучшую интеграцию с CDN и кэширование в браузере.

Manganis поддерживает широкий спектр форматов, применяя оптимизацию к таким ассетам, как CSS, JavaScript, изображениям, видео и многим другим.

В Dioxus 0.5 мы выпустили Manganis в "альфа" статусе, и в версии 0.6 стабилизировали его. Мы скорретировали API, поэтому вам потребуется обновить любой существующий код, который уже его использует. Наша новая реализация стала гораздо более надежной, устранив многие баги, с которыми сталкивались пользователи после выпуска версии 0.5.

Наша новая система использует компоновщик для извлечения расположения ассетов из скомпилированного бинарного файла. Это довольно сложная техника, и нам потребовалось время, чтобы реализовать её правильно, но мы уверены, что в долгосрочной перспективе это более надёжное решение. Если вы заинтересованы во внедрении Manganis в свои библиотеки и приложения (например, в Bevy!), у нас есть руководство специально для этого.


Suspence и HTML стриминг для Web

Асинхронность является основным компонентом любого UI фреймворка. Dioxus предоставляет хуки для управления асинхронным состоянием. Вы можете запустить future и обрабатывать состояние её загрузки и выполнения внутри компонента:

fn Article() -> Element {
    // Use resource starts a future and returns the current state
    let article = use_resource(fetch_article);

    rsx! {
        // You can `match` the state of the future.
        match article() {
            Some(article) => rsx! { "{article}" },
            None =>  rsx! { p { "Loading..." } }
        }
    }
}

Это работает нормально, если у вас есть одна future, но быстро становится запутанным, когда нужно объединить несколько future в одном пользовательском интерфейсе.

#[component]
fn Article() -> Element {
    // Use resource starts a future in the background and returns the current state
    let Some(title) = use_resource(fetch_title).cloned() else {
        return rsx! { "loading..." }
    };

    let Some(article) = use_resource(fetch_article).cloned() else {
        return rsx! { "loading..." }
    };

    let Some(category) = use_resource(move || article.title()).cloned() else {
        return rsx! { "loading..." }
    };

    rsx! {
        Title { "{title}" }
        Body { category, article }
    }
}

В дополнение к хукам нам нужен способ отображать другое состояние во время асинхронной загрузки. В Dioxus 0.6 представлен новый основной примитив для асинхронного пользовательского интерфейса — suspense boundaries (границы ожидания).

Suspense boundaries — это компонент, который отображает placeholder, когда любой дочерний компонент находится в состоянии загрузки:

rsx! {
    SuspenseBoundary {
        fallback: |context: SuspenseContext| rsx! {
            // Render a loading placeholder if
            // any child component is "suspended"
            "Loading..."
        },
        Article {}
    }
}

В любом дочернем компоненте вы можете просто передать состояние ожидания с помощью ?, чтобы приостановить рендеринг до завершения future:

fn Article() -> Element {
    let title = use_resource(fetch_title).suspend()?;
    let article = use_resource(fetch_article).suspend()?;
    let category = use_resource(move || article.title()).suspend()?;

    // Since we bubbled up all the pending futures with `?` we can just
    // handle the happy path in the component
    rsx! {
        Title { "{title}" }
        Body { category, article }
    }
}

Вместе с suspense boundaries, dioxus fullstack также поддерживает потоковую передачу каждого такого блока с сервера. Вместо ожидания загрузки всей страницы, dioxus fullstack передает каждый фрагмент с завершенными future по мере их готовности.

Многие из этих функций находятся на переднем крае технологий и только начинают появляться в фреймворках экосистемы JavaScript. Реализовать их в Dioxus было довольно сложно. Мы хотели поддерживать как fullstack веб-приложения, так и нативные desktop и mobile приложения. Эти две платформы часто предъявляют противоречивые требования к дизайну.

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


Static Site Generation и ISG

В рамках работы над стримингом мы также решили поддержать еще одну передовую фичу: инкрементальную статическую генерацию (ISG) и ее аналог — генерацию статических сайтов (SSG).

SSG — это техника, используемая во многих веб-фреймворках, таких как Jekyll, Hugo или Zola, для создания статических .html файлов, не зависящих от JavaScript. Сайты, такие как блоги и портфолио, часто используют SSG, поскольку такие платформы, как GitHub Pages, позволяют бесплатно размещать статические сайты. Фактически, этот сайт документации использует Dioxus SSG, развернутый на GitHub Pages! SSG помогает улучшить SEO и ускорить загрузку страниц для ваших пользователей.

В Dioxus 0.6 мы добавили поддержку SSG "из коробки" для всех fullstack проектов. Просто добавьте server function в свое приложение с именем static_routes, которая возвращает список маршрутов, которые dx должен сгенерировать:

#[server(endpoint = "static_routes")]
async fn static_routes() -> Result<Vec<String>, ServerFnError> {
    Ok(Route::static_routes()
        .into_iter()
        .map(|route| route.to_string())
        .collect::<Vec<_>>())
}

Теперь, если вы хотите сгенерировать статические файлы .html, добавьте флаг --ssg к команде dx build:

dx build --platform web --ssg

SSG основана на новой функции в Dioxus, называемой инкрементальной генерацией сайтов (ISG). Эта техника, похожая на генерацию статических сайтов, при которой сервер создает страницы по запросу и кэширует их в файловой системе. Это позволяет серверу хранить в кэше огромное количество страниц (например, для интернет-магазина с тысячами товаров), которые периодически становятся недействительными. ISG является несколько продвинутой технологией, но она необходима при использовании SSG:

fn main() {
        dioxus::LaunchBuilder::new()
        .with_cfg(server_only! {
            ServeConfig::builder()
                // turn on incremental site generation with the .incremental() method
                .incremental(IncrementalRendererConfig::new())
                .build()
                .unwrap()
        })
        .launch(|| {
            rsx! {
                Router::<Route> {}
            }
        })
}

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


Элементы документа: Title {} , Link {} , Stylesheet и Meta {}

До настоящего времени выполнение казалось бы простых операций на JavaScript в Dioxus было довольно неудобным. Из-за нашего кроссплатформенного характера нам приходилось искать решения, которые работали бы в вебе, десктопных и мобильных устройствах с единой абстракцией.

В Dioxus 0.6 мы добавили специальные элементы в модуле document, которые позволяют взаимодействовать с HTML document объектом без необходимости писать дополнительный код на JavaScript.

Теперь, чтобы установить заголовок вашего HTML-документа, просто используйте компонент document::Title {}:

use dioxus::prelude::*;
use dioxus::document::Title;

fn main() {
    dioxus::launch(|| rsx! {
        Title { "WebAssembly rocks!" }
        h1 { "A site dedicated to webassembly" }
    })
}

Соответственно, заголовок страницы будет обновлен:

Аналогично, с помощью компонентов Link, Stylesheet и Style вы можете включать элементы, которые автоматически объединяются с <head> элементом документа. Во время server side рендеринга эти ссылки собираются, удаляются дубликаты и минимизируются. С этими document встроенными компонентами вы можете быть уверены, что ваш элемент <head> настроен правильно для предварительной загрузки крупных ассетов, таких как таблицы стилей и внешние скрипты JavaScript.

fn app() -> Element {
    rsx! {
        Title { "WebAssembly rocks!" }
        Stylesheet { href: asset!("/assets/main.css") }
        h1 { "A site dedicated to webassembly" }
    }
}

Question Mark Error Handling

С этим релизом мы изменили структуру Element: теперь это не Option<Node>, а Result<Node>. Это означает, что мы наконец-то можем дать возможность использовать типичную обработку ошибок Rust в компонентах:

fn Slider() -> Element {
    let value: f64 = "1234".parse()?;

    rsx! {
        Handle { offset: value }
    }
}

Новый RenderError работает подобно типу Error из библиотеки anyhow: он может принимать любой тип dyn std::Error и прокидывать его вверх до ближайшей границы обработки ошибок (error boundary).

fn Input() -> Element {
    rsx! {
        ErrorBoundary {
            handle_error: |errors| rsx! {
                h3 { "Oops, we encountered an error.!" }
                pre { "Please report {errors:?} to the developers." }
            },
            Slider {}
        }
    }
}

Что ещё лучше: синтаксис ? также работает в EventHandlers, поэтому вы можете быстро добавлять такие элементы, как server functions, в свое приложение, не беспокоясь о ручной обработке ошибок.

fn Counter() -> Element {
    let mut data = use_signal(|| Data::default());

    rsx! {
        button {
            onclick: move |_| async move {
                // the `?` automatically throws this error upwards
                data.set(request_server_data().await?);
                Ok(())
            },
            "{data}"
        }
    }
}

Новый синтаксис позволяет Suspense и HTML стримингу возвращать ошибки во время рендеринга, не приводя к сбою всей страницы.


Синхронный prevent_default

Помимо возможности доступа к нативному типу события, в Dioxus 0.6 вся обработка событий теперь выполняется синхронно. Ранее вся обработка событий в Dioxus происходила вне обычного потока обработки событий браузера, чтобы поддерживать такие платформы, как dioxus-desktop, которым необходимо взаимодействовать с хостовым webview через слой межпроцессного взаимодействия (IPC). С этим релизом, мы наконец-то разобрались, как включить блокирующую коммуникацию для dioxus-desktop, благодаря чему мы наконец-то можем сделать обработку событий синхронной!

Таким образом, больше не требуется использовать специальный атрибут dioxus_prevent_default, и теперь вы можете напрямую вызывать event.prevent_default().

fn Form() -> Element {
    rsx! {
        button {
            // we no longer need this!
            dioxus_prevent_default: "onclick",

            // instead we can just call .prevent_default()
            onclick: move |evt| {
                evt.prevent_default();
                todos.write().remove(&id);
            },
        }
    }
}

Теперь стало возможным условно применять prevent_default, что ранее было ограничением в Dioxus. Компоненты, такие как Link {}, теперь ведут себя точно так же, как их нативные аналоги, что решает давние проблемы в приложениях на Dioxus.


Отслеживание размера при помощи onresize

Благодаря сообществу у нас теперь есть два специальных обработчика, которых нет в спецификации HTML: onvisible и onresize. Эти обработчики являются "особенными" обработчиками Dioxus, которые автоматически настраивают IntersectionObserver, ранее требовавший JavaScript.

Теперь вы можете реализовывать расширенные взаимодействия с минимальными усилиями:

fn app() -> Element {
    let mut items = use_signal(|| 100);

    rsx! {
        // Adding a value will cause the `div` to be re-rendered with an extra div
        button { onclick: move |_| items += 1, "Add one" }

        div {
            // This will be called when the `div` is resized
            onresize: move |data| {
                tracing::info!("resized to {:#?}", data.get_border_box_size().unwrap());
            },

            for x in 0..items() {
                div { "{x}" }
            }
        }
    }
}

Отслеживание видимости при помощи onvisible

Помимо onresize, у нас теперь есть специальный обработчик, отсутствующий в спецификации HTML: onvisible.

fn app() -> Element {
    rsx! {
        div {
            onvisible: move |data| {
                println!("visible!");
            }
            "Hello world!"
        }
    }
}

Это позволяет добавлять сложные анимации в ваше приложение без необходимости писать кастомный JavaScript.


Гибридные WGPU Overlays

В этом релизе добавлена функция "дочернего окна" для Dioxus Desktop, которая позволяет накладывать нативные приложения Dioxus поверх существующих окон. Это упрощает интеграцию Dioxus в качестве оверлея поверх других рендереров, таких как WGPU и OpenGL.


Поддержка сборки Web, iOS и Android приложений

Мы добавили поддержку веба и мобильных платформ в dx bundle. Ранее dx bundle работал только для десктопных приложений. Теперь вы можете создавать сборки для самых разных платформ:

  • macOS (.app, .dmg)

  • Windows (.exe, .msi)

  • Linux (.deb, .rpm, .appimage)

  • Android (.apk)

  • iOS (.ipa, .app)

  • Web (.appimage, /public folder)


JSON вывод для CI / CLI

В рамках переработки CLI мы также добавили режим в формате json-output. Теперь, если вы передадите флаг --json-output командам в Dioxus CLI, логи будут выводиться в json формате:

Это особенно важно для пользователей dx bundle, которые хотят автоматически загружать свои сборки на хостинг-провайдера по своему выбору. Вы можете легко комбинировать вывод dx с инструментом, таким как jq, чтобы извлекать важную информацию, например, результаты сборки, с помощью простого однострочного скрипта:


Новые стартовые шаблоны

Dioxus 0.6 поставляется с тремя новыми стартовыми шаблонами для кроссплатформенных приложений. Каждый шаблон представляет собой полнофункциональное приложение, готовое к использованию в продакшене, которое можно использовать как отправную точку для создания собственных приложений на Dioxus.

  1. Bare-Bones: Минимальный стартовый шаблон без стилей, ресурсов или структуры.

  2. Jumpstart: Шаблон с базовой структурой, компонентами и несколькими страницами.

  3. Workspace: Шаблон с раздельными крейтами для веба, десктопных и мобильных платформ.

Эти шаблоны встроены прямо в команду dx new — просто запустите dx new и следуйте инструкциям, чтобы выбрать нужный шаблон.


Nightly документация, туториалы и новые гайды

Как обычно, в крупных релизах, Dioxus 0.6 включает значительное обновление документации. Мы полностью переработали учебное руководство, сделав его менее перегруженным кодом. Новый туториал теперь сосредоточен на основах, таких как добавление ассетов и развертывание в продакшене.

Сайт документации теперь включает все "современные" версии Dioxus: 0.3, 0.4, 0.5 и 0.6 доступны на одном top-level веб-сайте. Ранее мы создавали отдельные ссылки на разные MDbooks, что со временем стало неудобным. Теперь вы можете просто переключаться между версиями прямо на сайте:

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

Новая документация также включает небольшие улучшения удобства использования, такие как навигационные цепочки:

а также новые блоки кода с интерактивными примерами:


Превью In-Place бинарного патчинга

Работая над новым hot-reloading engine, мы экспериментировали с добавлением полноценным hot-reloading кода на Rust в приложениях Dioxus. Эта идея была вдохновлена целью Эндрю Келли по реализации "in-place-binary-patching" в Zig. К сожалению, у нас не было возможности выпустить прототип для этого релиза. (слишком много других фич!), но мы создали небольшой прототип:

Вероятно, у нас не будет времени реализовать полноценный hot-reloading кода на Rust в версии 0.7, но следите за новостями в начале следующего года!


Небольшие изменения:

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

  • Поддержка системного трея: Теперь у нас снова есть полноценная поддержка системных треев благодаря замечательному вкладу сообщества.

  • Пользовательские циклы событий: Теперь вы можете предоставить собственный цикл событий (event loop), что позволяет использовать Dioxus в средах, где уже существуют другие окна.

  • dioxus-document: Мы вынесли нашу document абстракцию в отдельный модуль, чтобы любой рендерер мог реализовать Document трейт для интеграции с Title {}, Script {} и eval.

  • dioxus-history: Мы также вынесли history абстракцию в отдельный модуль, чтобы другие рендереры могли воспользоваться Link и Router без необходимости включения специального флага в dioxus-router.

  • eval API был упрощен, чтобы поддерживать вызовы .recv::<T>().await на evals, что облегчает взаимодействие с JavaScript.

  • dx fmt: Теперь поддерживает атрибуты #[rustfmt::skip], учитывает настройки rustfmt.toml и стал значительно более надежным.


Обновление версии с 0.5 до 0.6

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

  • Изменения в синтаксисе asset!()

  • Небольшие изменения в API eval()

  • Миграция на prevent_default()

  • Замена VNode::None на rsx! {} для пустых узлов

Мы подготовили руководство по миграции, чтобы вам было проще перейти на новую версию.


Заключение

На этом всё для этого выпуска! Мы исправили множество проблем, включая ошибки сборки, ложные hot-reloading’и и совместимость с редкими платформами и редакторами.

Dioxus 0.6 находился в альфа-версии довольно долго, и мы очень благодарны всем, кто участвовал в тестировании и помог сделать этот выпуск самым отточенным на сегодняшний день. Управлять таким крупным проектом с открытым исходным кодом — задача не из легких. Выпуск занял гораздо больше времени, чем мы рассчитывали, потребовав два цикла разработки вместо одного.

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

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

Мы планируем поддерживать 0.6 в течение длительного времени. Вместо того чтобы сразу добавлять новые функции, мы сосредоточимся на создании обучающих видео, написании документации, исправлении ошибок, улучшении производительности и взаимодействии с сообществом. Команда Dioxus хочет потратить время на создание собственных приложений!

Тем не менее, у нас есть несколько крупных задач, запланированных на Dioxus 0.7 и дальнейшие выпуски:

  • Hot-reloading кода на Rust с бинарным патчингом

  • Интеграция разделения wasm пакетов в роутере

  • dx deploy для развертывания на хостинговых платформах (Fly.io, AWS, Cloudflare и др.)

Мы также ищем новых сотрудников — если вы хотите работать над Dioxus вместе с нами в Сан-Франциско (или удаленно), свяжитесь с нами!


Спасибо нашему сообществу!

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

@ASR-ASU - @Aandreba - @Andrew15-5 - @DogeDark - @Klemen2 - @LeWimbes - @LeoDog896 - @MrGVSV - @Rahul721999 - @Septimus - @Tahinli - @WilliamRagstad - @ahqsoftwares - @airblast-dev - @alilosoft - @azamara - @chungwong - @d3rpp - @daixiwen - @dependabot - @ealmloff - @hackartists - @hardBSDk - @houseme - @i123iu - @ilaborie - @imgurbot12 - @jacklund - @jingchanglu - @luveti - @marc2332 - @matthunz - @nayo0513 - @opensource-inemar-net - @oskardotglobal - @panglars - @pyrrho - @ribelo - @rogusdev - @ryo33 - @samtay - @sknauff - @srid - @tigerros - @tpoliaw - @uzytkownik


Ссылки

Интересные ссылки с комментариями к релизу:

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