Skip to content

Releases: DioxusLabs/dioxus

v0.6.0-alpha.5

16 Nov 05:15
a0e649a
Compare
Choose a tag to compare
v0.6.0-alpha.5 Pre-release
Pre-release

v0.6.0-alpha.5

This should be the final pre-release of 0.6. We are currently in a feature-freeze and any changes from here will be bug fixes and upgrades to documentation, should there need any.

A draft of the release is available at http://dioxuslabs.com/blog/release-060/.

alpha.4 and alpha.2 have much larger change lists for the full release cycle:
https://github.com/DioxusLabs/dioxus/releases/tag/v0.6.0-alpha.4
https://github.com/DioxusLabs/dioxus/releases/tag/v0.6.0-alpha.2

dx serve --platform android

In the last release we added support for iOS serve and now we are adding support for android serve!

image

faster wasm-bindgen and faster builds

We enabled the "parallel" feature on walrus and configured out logs to boost wasm-bindgen performance by 2-3x. When combined with debug=0, incremental builds are about 70-80% faster.

Deprecate relative asset paths

We are phasing out asset!("./assets/plah.png") in favor of the web-native syntax: asset!("/assets/plah.png"). This now throws a deprecation warning.

Fixes to reactivity

We fixed some show-stopper bugs with reactivity around ReadOnlySignals on component boundaries

CLI json output

The CLI now has a mode to emit logs in json so you can combine it with tools like jq for better script interoperability.

What's Changed

New Contributors

Full Changelog: v0.6.0-alpha.4...v0.6.0-alpha.5

v0.6.0-alpha.4

01 Nov 23:52
e0575b3
Compare
Choose a tag to compare
v0.6.0-alpha.4 Pre-release
Pre-release

Dioxus v0.6.0-alpha.4

This release is planned to be the last release of the v0.6 alpha cycle fixing a number of bugs with hotreloading, assets, the router, and more.

To install the CLI (instead of building from source) use:

cargo binstall dioxus-cli --version v0.6.0-alpha.4

Major changes in this alpha:

Inline iOS support, android fixes:

bothmainmobile

Overhaul of the CLI:

We dropped the custom scroll behavior of the previous alpha in favor of a simple fixed viewport and traditional println!()-oriented history.

This provides more details while also allowing scrollback/selection/etc.

Screenshot 2024-10-13 at 10 18 50 PM

Hotreloading for manganis assets in all platforms (except Android)

All asset!() calls now support hotreloading:

bundled-ios-reload.mp4

Asset system changes

We adjusted the path format of the asset!() macro to force leading slashes. This will eventually let us support relative paths to assets as well as make it clear that you cannot include assets from outside the package directory:

Screenshot 2024-10-15 at 8 35 48 PM

onresize handler

You can now attach onresize to your elements and track changes to element size without an Observer.

Fullstack server functions for iOS/Android/Desktop

By default, in dev, server functions are now callable from native apps without any additional configuration.

Keep in mind that in production you will still want to set the endpoint of your server.

Improved compile times

We cut the workspace into smaller pieces that include fewer dependencies. This should improve build times by about 50%.

Docsite improvements

We have been using the docsite as a canary for many of the new features (like static-site-generation) and you can test drive it at https://dioxuslabs.com.

Bug fixes

We fixed a ton of bugs, so things should be more reliable, faster, and hopefully more intuitive.

Known issues remaining:

  • non-serve commands are too verbose
  • dx bundle is pointing to the wrong directory
  • base_path is getting set properly in some scenarios

What's Changed

Read more

v0.6.0-alpha.2

07 Aug 23:39
506d47f
Compare
Choose a tag to compare
v0.6.0-alpha.2 Pre-release
Pre-release

Dioxus 0.6.0 Alpha

Dioxus 0.6 includes improvements to several areas of dioxus. The highlights are:

  • Asset improvements
  • Head elements
  • RSX autocomplete
  • Improved hot reloading
  • Suspense and streaming
  • Error boundaries
  • A new TUI!
  • Documentation improvements
  • Blitz rewrite

Asset Stabilization

We introduced our new asset system, Manganis, in an alpha state with the 0.5 release. Dioxus 0.6 stabilizes the asset system and fixes several bugs and performance issues. You can try out the new linker based asset system by including an asset! anywhere in your code. It will automatically be optimized and bundled across all platforms:

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

Head Elements

In addition to the Manganis asset system, dioxus 0.6 includes a new way to include assets into your html. The new Script, Link, Style , and Meta components let you link to assets anywhere in your html. These components will automatically be hoisted into the <head> across all platforms and deduplicated by the source:

#[component]
fn MyStyledComponent() -> {
    rsx! {
        head::Link {
            rel: "stylesheet",
            href: asset!("./assets/style.css")
        }
        "This component is styled"
    }
}

Autocomplete and improved errors for RSX

RSX now supports autocomplete everywhere. In addition to expressions, elements, components and attributes now autocomplete correctly:

autocomplete.mov

The new version of RSX also features better error messages for incorrect markup:

Incorrect markup error message

Supercharged Hot Reloading

In 0.6, RSX hot reloading is much more consistent. You can move around and duplicate expressions anywhere in an rsx block or create new literals anywhere in an rsx block. This means you can now create new formatted text nodes, new formatted attributes or tweak properties on the fly without recompiling!

hot-reloading.mov

Suspense and Streaming

Async is a core component of any UI framework. Dioxus provides hooks to handle async state. You can start a future and handle the loading and resolved states within the component:

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

    rsx! {
        // You can match the state of the future to render either a loading state or the resolved state
        match article() {
            Some(article) => rsx! { "{article}" },
            None =>  rsx! { p { "Loading..." } }
        }
    }
}

This works ok if you have a single future, but it quickly gets messy when combining many futures into one UI:

#[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 }
    }
}

In addition to hooks, we need a way to display a different state when async is loading. Dioxus 0.6 introduces a new core primitive for async UI called suspense boundaries. A suspense boundary is a component that renders a placeholder when any child component is loading:

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

In any child component, you can just bubble up the pending state with ? to pause rendering until the future is finished:

#[component]
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 }
    }
}

Along with suspense boundaries, dioxus fullstack also supports streaming each suspense boundary in from the server. Instead of waiting for the whole page to load, dioxus fullstack streams in each chunk with the resolved futures as they finish:

streaming.mov

Error boundaries

0.6 also introduces error boundaries which let you display an error message if any child component runs into an error:

#[component]
fn Root() -> Element {
    rsx! {
        ErrorBoundary {
            handle_error: |errors: ErrorContext| {
                match errors.show() {
                    // Render the view the child component through with the error
                    Some(view) => view,
                    // Or a fallback if the error doesn't come with a view
                    None => rsx! {
                        pre {
                            color: "red",
                            "oops, we ran into an error\n{errors:#?}"
                        }
                    }
                }
            },
            Contents {}
        }
    }
}

You can throw an error from any child component while rendering or handling events:

#[component]
fn Double(input: String) -> Element {
    // You can use ? to throw an event during rendering
    let parsed: f32 = input.parse()?;
    let doubled = parsed * 2.0;
    
    rsx! {
        "{doubled}"
    }
}

#[component]
fn DoubleButton(mut count: Signal<u8>) -> Element {
    rsx! {
        button {
            onclick: move |_| {
                // Errors can have an associated view which the error boundary can
                // choose to show
                let doubled = count().checked_mul(2).show(|_|
                    rsx! { "multiplying {count} by 2 would overflow the u8" }
                )?;
                count.set(doubled);

                Ok(())
            },
            "Double!"
        }
    }
}

DX TUI

The Dioxus CLI has been rewritten to support a TUI with build progress, and multiple views for logs. It has shortcuts for common actions, and displays progress in both the TUI and the site as the project loads:

tui.mov

Blitz Rewrite

Blitz has been rewritten to use Firefox's browser engine, Stylo. The new version of Blitz is much more capable with proper accessibility support, IME support, and better text support. Blitz should be a drop in replacement for dioxus desktop for the small subset of HTML it supports. Keep in mind Blitz is still experimental and not ready for production use. You can try Blitz by adding dioxus_blitz from the git repo:

cargo add dioxus-blitz --git https://github.com/DioxusLabs/blitz

Launching your Dioxus app with the blitz renderer:

dioxus_blitz::launch(app);

Dioxus with Blitz

Ergonomic tweaks

Dioxus 0.6 also includes a number of smaller ergonomic tweaks that should help dioxus feel a lot more consistent

Static Generation

Dioxus 0.6 splits out static generation into its own platform to make it easier to set up:

//! Static generation works out of the box with the router. Just add a router anywhere in your app and it will generate any static routes for you!

#![allow(unused)]
use dioxus::prelude::*;

// Generate all routes and output them to the static path
fn main() {
    launch(|| {
        rsx! {
            Router::<Route> {}
        }
    });
}

#[derive(Clone, Routable, Debug, PartialEq)]
enum Route {
    #[route("/")]
    Home {},

    #[route("/blog")]
    Blog,
}

#[component]
fn Blog() -> Element {
    rsx! {
        Link { to: Route::Home {}, "Go to counter" }
        table {
            tbody {
                for _ in 0..100 {
                    tr {
                        for _ in 0..100 {
                            td { "hello!" }
                        }
                    }
                }
            }
        }
    }
}

#[component]
fn Home() -> Element {
    let mut count = use_signal(|| 0);

    rsx! {
        Link { to: Route::Blog {}, "Go to blog" }
        div {
            h1 { "High-Five counter: {count}" }
            button { onclick: move |_| count += 1, "Up high!" }
            button { onclick: move |_| count -= 1, "Down low!" }
        }
    }
}

Fullstack State

Fullstack state now propagates from the launch builder into server functions which makes it much easier to set up state that is shared throughout your application like a database pool:

fn main() {
     LaunchBuilder::new().with_context(1234567890u32).launch(app);
}

#[server]
async fn get_server_data() -> Result<String, ServerFnError> {
     let FromContext(context): FromContext<u32> = extract().await?;
     Ok(format!("the context was {context}"))
}

Callbacks

Dioxus 0.6 expands EventHandlers into callbacks which let you bot...

Read more

v0.5.1: Bug fixes!

05 Apr 00:14
9c5e5f9
Compare
Choose a tag to compare

0.5.1: Bug Fixes!

Thanks everyone for the great feedback for the 0.5.0 launch! We're releasing 0.5.1 now with a bunch of bug fixes.

This includes some stuff like fixing async polling, some smalls issues with memos and resources, and a memory leak in EventHandler.

We strongly recommend you upgrade your dioxus project with cargo update!

The autoformatter also changed a bit, so if you're using the VSCode extension, you should get the updates automatically.

What's Changed

New Contributors

Full Changelog: v0.5.0...v0.5.1

v0.5.0

28 Mar 01:27
f6c3b27
Compare
Choose a tag to compare

Dioxus 0.5: Signal Rewrite, Remove lifetimes/unsafe, CSS Hotreloading, 5x Faster Desktop, Asset System, and more!

Read the Full 0.5 release post on the Dioxus blog

The story


Here at Dioxus Labs, we have an unofficial rule: only one rewrite per year.

Our last rewrite brought some amazing features: templates, hotreloading, and insane performance. However, don’t be mistaken, rewrites are scary, time consuming, and a huge gamble. We started this new rewrite on January 1st of 2024, completed it by Feburary 1st, and then spent another month and a half writing tests, squashing bugs, and polishing documentation. Rewrites are absolutely not for the faint of heart.

If you’re new here, Dioxus (dye•ox•us) is a library for building GUIs in Rust. Originally, I built Dioxus as a rewrite of Yew with the intention of supporting proper server-side-rendering. Eventually, Dioxus got popular, we got some amazing sponsors, and I went full time. We’ve grown from a team of 1 (me) to a team of 4(!) - pulled entirely from the wonderful dioxus community.

Now, Dioxus is something a little different. Real life, actual companies are shipping web apps, desktop apps, and mobile apps with Dioxus. What was once just a fun little side project powers a small fraction of apps out in the wild. We now have lofty goals of simplifying the entire app development ecosystem. Web, Desktop, Mobile, all end-to-end typesafe, blazing fast, living under one codebase. The dream!

With 0.5 we took a hard look at how Dioxus would need to change to achieve those goals. The request we got from the community was clear: make it simpler, make it robust, make it polished.

What’s new?


This is probably the biggest release of Dioxus ever, with so many new features, bug fixes, and improvements that I can’t list them all. We churned over 100,000 lines of code (yes, 100,000+) with over 1,400 commits between 0.4.3 and 0.5.0. Here’s a quick overview:

  • Complete rewrite of dioxus-core, removing all unsafe code
  • Abandoning use_state and use_ref for a clone-free Signal-based API
  • Removal of all lifetimes and the cx: Scope state
  • A single, unified launch function that starts your app for any platform
  • Asset hotreloading that supports Tailwind and Vanilla CSS
  • Rewrite of events, allowing access to the native WebSys event types
  • Extension of components with element properties (IE a Link now takes all of <a/> properties)
  • Integrated Error Boundaries and Server Futures with Suspense integration
  • 5x faster desktop reconciliation and custom asset handlers for streaming bytes
  • Streaming server functions and fullstack hotreloading
  • Tons of QoL improvements, bug fixes, and more!
💡 If you are updating from DIoxus 0.4, a migration guide is available

Lifetime Problems


To make Dioxus simpler, we wanted to remove lifetimes entirely. Newcomers to rust are easily scared off by lifetime issues, and even experienced Rustaceans find wading through obtuse error messages exhausting.

In dioxus 0.1-0.4, every value in a component lives for a 'bump lifetime. This lifetime lets you easily use hooks, props and the scope within event listeners without cloning anything. It was the chief innovation that made Dioxus so much easier to use than Yew when it was released.

// Scope and Element have the lifetime 'bump
fn OldDioxusComponent(cx: Scope) -> Element {
  // hook has the lifetime 'bump
  let mut state = use_state(cx, || 0);
  cx.render(rsx! {
    button {
      // The closure has the lifetime 'bump which means you don't 
      // need to clone hook before you move it into the closure 
      onclick: move |_event| *state += 1,
    }
  })
}

This works great for hooks most of the time. The lifetime lets you omit a bunch of manual clones every time you want to use a value inside an EventHandler (onclick, oninput, etc).

However, the lifetime doesn’t work for futures. Futures in dioxus need to be 'static which means you always need to clone values before you use them in the future. Since a future might need to run while the component is rendering, it can’t share the component’s lifetime.

// Scope and Element have the lifetime 'bump
fn OldDioxusComponent(cx: Scope) -> Element {
  // state has the lifetime 'bump
  let state = use_state(cx, || 0);
  
  cx.spawn({
    // Because state has the lifetime 'bump, we need to clone it to make it 
    // 'static before we move it into the 'static future
    let state = state.clone();
    async move {
      println!("{state}");
    }
  });

  // ...
}

If you don’t clone the value, you will run into an error like this:

4  |   fn OldDioxusComponent(cx: Scope) -> Element {
   |                         --
   |                         |
   |                         `cx` is a reference that is only valid in the function body
   |                         has type `&'1 Scoped<'1>`
...
8  | /     cx.spawn(async move {
9  | |         println!("{state}");
10 | |     });
   | |      ^
   | |      |
   | |______`cx` escapes the function body here
   |        argument requires that `'1` must outlive `'static`

The error complains that cx must outlive 'static without mentioning the hook at all which can be very confusing.

Dioxus 0.5 fixes this issue by first removing scopes and the 'bump lifetime and then introducing a new Copy state management solution called signals. Here is what the component looks like in dioxus 0.5:

// Element has no lifetime, and you don't need a Scope
fn NewComponent() -> Element {
  // state is 'static and Copy, even if the inner value you store is not Copy
  let mut state = use_signal(|| 0);

  // State is already 'static and Copy, so it is copied into the future automatically
  spawn(async move {
    println!("{state}");
  });

  rsx! {
    button {
      // The closure has the lifetime 'static, but state is copy so you don't need to clone into the closure
      onclick: move |_event| state += 1,
    }
  }
}

While this might seem like a rather innocuous change, it has an impressively huge impact on how easy it is to write new components. I’d say building a new Dioxus app is about 2-5x easier with this change alone.

Goodbye scopes and lifetimes!


In the new version of dioxus, scopes and the 'bump lifetime have been removed! This makes declaring a component and using runtime functions within that component much easier:

You can now declare a component by just accepting your props directly instead of a scope parameter

#[component]
fn MyComponent(name: String) -> Element {
  rsx! { "Hello {name}!" }
}

And inside that component, you can use runtime functions directly

spawn(async move {
  tokio::time::sleep(Duration::from_millis(100)).await;
  // You can even use runtime functions inside futures and event handlers!
  let context: i32 = consume_context();
});

Now that lifetimes are gone, Elements are 'static which means you can use them in hooks or even provide them through the context API. This makes some APIs like virtual lists in dioxus significantly easier. We expect more interesting APIs to emerge from the community now that you don’t need to be a Rust wizard to implement things like virtualization and offscreen rendering.

Removal of all Unsafe in Core


Removing the 'bump lifetime along with the scope gave us a chance to remove a lot of unsafe from dioxus. dioxus-core 0.5 contains no unsafe code 🎉

Screenshot_2024-02-22_at_5 45 36_PM

There’s still a tiny bit of unsafe floating around various dependencies that we plan to remove throughout the 0.5 release cycle, but way less: all quite simple to cut or unfortunately necessary due to FFI.

Signals!


Dioxus 0.5 introduces Signals as the core state primitive for components. Signals have two key advantages over the existing use_state and use_ref hooks: They are always Copy and they don’t require manual subscriptions.

Copy state

Signal<T> is Copy, even if the inner T values is not. This is enabled by our new generational-box crate (implemented with zero unsafe). Signals can even optionally be Send+Sync if you need to move them between threads, removing the need for a whole class of specialized state management solutions.

The combination of Copy + Send + Sync Signals, and static components makes it incredibly easy to move state to anywhere you need it:

fn Parent() -> Element {
  // We use a sync signal here so that we can use it in other threads, 
  // but you could use a normal signal if you have !Send data
  let mut state = use_signal_sync(|| 0);

  spawn(async move {
    // Signals have a ton of helper methods that make them easy to work with. 
    // You can call a signal like a function to get the current value
    let value: i32 = state();
  });

  // Because signals can be sync, we can copy them into threads easily
  std::thread::spawn(move || {
    loop {
      std::thread::sleep(Duration::from_millis(100));
      println!("{state}");
    }
  });

  render! {
    button {
      // You can easily move it into an event handler just like use_state
      onclick: move |_| state += 1
    }
  }
}

With Copy state, we’ve essentially bolted on a light form of garbage collection into Rust that uses component lifecycles as the triggers for dropping state. From a memory perspective, this is basically the same as 0.4, but with the added benefit of...

Read more

v0.5.0-alpha.0: first prerelease

23 Feb 02:36
8219b11
Compare
Choose a tag to compare
Pre-release

First prerelease of dioxus

v0.5 is coming soon! We've decided to start putting out pre-releases so developers on the "bleeding-edge" have a stable checkpoint to use as we release new breaking features.

The full release notes for 0.5 are here:

https://dioxus.notion.site/Dioxus-0-5-Signals-Unified-Launch-Native-Events-5x-Faster-Desktop-Error-Boundaries-9961963b731a4d9f8465e5bcdf8e9ab3?pvs=74

Migration guide:

https://ealmloff.github.io/docsite/learn/0.4/migration/

Feel free to hop into the discord to give feedback and/or chat about the new changes.

Full Changelog: v0.4.3...v0.5.0-alpha.0

v0.4.3

23 Feb 02:28
d3f6ff7
Compare
Choose a tag to compare

v0.4.3

This is the last release of the 0.4 cycle, containing a number of useful new features as well as many bug fixes.

You can now manipulate the dioxus runtime without going through the Scope object.

This was originally released many months ago, but we never made the release post.

What's Changed

Read more

v0.4.2

07 Dec 00:37
da4794d
Compare
Choose a tag to compare

What's Changed

New Contributors

Full Changelog: v0.4.0...v0.4.2

v0.4.1

04 Sep 20:12
d5d974d
Compare
Choose a tag to compare

What's Changed

v0.4.0

02 Aug 17:15
f80c3c9
Compare
Choose a tag to compare

Dioxus 0.4 Github

The Dioxus 0.4 release includes 6 new crates, a ton of new features and a plethora of bug fixes!

Highlights:

  • Rewritten Type safe Router
  • Fullstack cross-platform meta framework
  • Suspense
  • CLI Linting
  • CLI Bundling
  • Rewritten Documentation
  • Cross platform system API wrappers: Dioxus STD

Router

The router has been revamped for the 0.4 release. The router now uses an enum to define routes. If you use this enum to link to a page, the compiler will insure you never link to a page that doesn’t exist. The new router also includes Nesting, Layout, and sitemap support:

use dioxus::prelude::*;
use dioxus_router::prelude::*;

#[derive(Routable, Clone)]
enum Route {
    #[route("/")]
    Home {},

    #[route("/blog")]
    Blog {},
}

fn App(cx: Scope) -> Element {
    render! {
        Router::<Route> {}
    }
}

#[inline_props]
fn Home(cx: Scope) -> Element {
    render! {
        Link {
            to: Route::Blog {},
            "Go to the blog"
        }
        h1 { "Welcome to the Dioxus Blog!" }
    }
}

#[inline_props]
fn Blog(cx: Scope) -> Element {
    render! {
        Link {
            to: Route::Home {},
            "Go to the home page"
        }
        h1 { "Blog" }
    }
}

Huge shoutout to @TeFiLeDo for creating many different prototypes and tests for the new router!

Fullstack

The 0.4 release introduces the Fullstack crate. The fullstack crate contains adapters for communicating with your

Fullstack Rendering

The fullstack crate makes it dead simple to create a server side rendered hydrated app with fullstack typesafety. The fullstack crate lets you render your page on the server on every request (or incrementally) and then hydrate it on the client.

use dioxus::prelude::*;
use dioxus_fullstack::prelude::*;

fn main() {
	LaunchBuilder::new(app).launch();
}

fn app(cx: Scope) -> Element {
	let mut count = use_state(cx, || 0);
	render! {
		h1 { "High-Five counter: {count}" }
		button { onclick: move |_| count += 1, "Up high!" }
		button { onclick: move |_| count -= 1, "Down low!" }
	}
}

Fullstack communication

In addition to fullstack rendering, the new fullstack create allows you to communicate with your server effortlessly. You can annotate a function with #[server] to make the code inside the function only run on the server. This makes it easy to build a backend for your web or desktop application!

use dioxus::prelude::*;
use dioxus_fullstack::prelude::*;

fn main() {
	LaunchBuilder::new(app).launch();
}

fn app(cx: Scope) -> Element {
	let mut count = use_state(cx, || 0);
	render! {
		h1 { "High-Five counter: {count}" }
		button { onclick: move |_| count += 1, "Up high!" }
		button { onclick: move |_| count -= 1, "Down low!" }
		button {
			onclick: move |_| {
				to_owned![count];
				async move {
					let double = double(*count).await.unwrap();
					count.set(double);
				}
			}
		}
	}
}

#[server]
async fn double(number: usize) -> Result<usize, ServerFnError> {
	// This will *only* run on the server
	Ok(number * 2)
}

Suspense

0.4 adds the long awaited suspense feature. This allows you to wait for a future on the server and then send the result to the client. You can combine suspense with server functions to wait for some code on your server to finish running before rendering a component:

use dioxus::prelude::*;
use dioxus_fullstack::prelude::*;

fn main() {
	LaunchBuilder::new(app).launch();
}

fn app(cx: Scope) -> Element {
	let mut server_data = use_server_future(cx, || get_server_data())?;

	render! {
		div {
			"{server_data:?}"
		}
	}
}

#[server]
async fn get_server_data() -> Result<usize, ServerFnError> {
	Ok(42)
}

CLI Improvements

The Dioxus CLI has moved into the dioxus main repo

The Dioxus CLI is now called dx instead of dioxus. The 0.4 release of the Dioxus CLI added three main features:

Dioxus Check

@eventualbuddha has done a fantastic job creating a new Dioxus check command to lint your Dioxus code for errors! It will warn you if your code violates the rules of hooks

dx check
Screenshot 2023-07-26 at 1 43 11 PM

Dioxus Bundle

The Dioxus CLI can now create installers for MacOs and Windows powered by tauri-bundle!

dioxus bundle
Screenshot 2023-07-26 at 1 50 31 PM

Desktop Hot Reload

In Dioxus 0.4, rsx hot reloading has moved from the hot reload macro to the CLI for desktop, liveview, fullstack, and TUI applications. Now every platform can use the CLI to start hot reloading:

dioxus serve --platform desktop --hot-reload

Mobile

Dioxus now has improved mobile support with a getting started guide and a mobile example!

Documentation

The documentation has been revamped for the 0.4 release. We now have a short getting started guide that teaches you how to build a hackernews clone in Dioxus.

The new documentation site takes full advantage of the fullstack crate to prerender the pages.

While working on the new docsite we also created two new crates:

  • Dioxus Mdbook makes it easy to use markdown into your Dioxus components and use Dioxus components in your markdown
  • Dioxus Search makes it easy to create instant search indexes for your Dioxus page's. It integrates with the Dioxus router's new site map feature to automatically detect searchable pages

Together these crates allow us to make our documentation fully interactive and instantly searchable. The new documentation site contains live code snippets of different components as you walk through the guide.

Dioxus STD

One of the biggest problems with cross platform development in rust today is finding ergonomic ways to interact with system APIs. @doge and @marc have created a new Dioxus std create that makes it easy to interact with a variety of system APIs in Dioxus across all platforms. It contains helpers for Geolocation, clipboard access, notifications, color schemes, translation, and more!

Async Eval

@doge has made the use_eval hook significantly more powerful for the 0.4 release of Dioxus. You can now send messages to and from Javascript asynchronously. This feature makes it possible to listen for Javascript events that Dioxus doesn’t officially support (for example the intersection observer API).

Dioxus HTML

The 0.4 release introduces file upload support for the dioxus-html crate. This makes it easy to upload files to you desktop, liveview, or web application.

This release also introduces a new onmounted event that provides access to some common node APIs like focusing an element or getting the size of an element in a cross platform way.

Rink and Blitz-core

Dioxus' TUI renderer Rink and WGPU renderer Blitz can now be used without Dioxus. This makes it possible to render your own html into either of these renderers or use these renderers in your own framework. To get started, see the Blitz and Rink framework-less examples.

Community

Office Hours

Dioxus now holds weekly office hours in the discord! If you are interested in the project, need help with your projects, or want to get started contributing, you should come to our weekly office hours!

The office hours happen every Friday at 9:00 AM (PDT) in the Dioxus discord server

Recordings of office hours are available on the Dioxus youtube channel

New contributors

There have been almost 50 new contributors since the 0.3 release!

@mirkootter, @davidpdrsn, @mwcz, @askreet, @marcerhans, @ndarilek, @arniu, @pickfire, @arqalite, @ProfXwing, @Icekey, @willothy, @rtwfroody, @attilio, @stephenandary, @Rigellute, @onweru, @Byron, @nicoburns, @serzhiio, @indiv0, @azriel91, @elliotwaite, @nmlt, @nicholastmosher, @TimothyStiles, @jpearnshaw, @jmsfltchr, @striezel, @echochamber, @xinglixing, @sean, @torsteingrindvik, @vanhouc, @terhechte, @traxys, @Mouradost, @DianQK, @eventualbuddha, @leahiel, @kaid, @frisoft, @Niedzwiedzw

Conclusion

For more information on the 0.4 release and all the new features that have been introduced, read the blogpost

Full Changelog: v0.3.2...v0.4.0