Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Leptos | 7,610 | 20 hours ago | 30 | mit | Rust | |||||
Build fast web applications with Rust. | ||||||||||
Sycamore | 2,079 | 8 | 4 days ago | 19 | June 26, 2022 | 47 | mit | Rust | ||
A library for creating reactive web apps in Rust and WebAssembly | ||||||||||
Binding.scala | 1,575 | 12 | 21 days ago | 119 | December 25, 2019 | 45 | mit | Scala | ||
Reactive data-binding for Scala | ||||||||||
Yox | 1,079 | 5 | 7 | a month ago | 639 | May 06, 2022 | 3 | mit | JavaScript | |
A lightweight mvvm framework | ||||||||||
Vue Composable | 1,025 | 5 | 4 months ago | 85 | October 17, 2021 | 20 | mit | TypeScript | ||
Vue composition-api composable components. i18n, validation, pagination, fetch, etc. +50 different composables | ||||||||||
Sinuous | 916 | 6 | 10 | 2 months ago | 108 | February 13, 2022 | 15 | JavaScript | ||
🧬 Light, fast, reactive UI library | ||||||||||
Reflex Platform | 681 | 2 months ago | 90 | bsd-3-clause | Nix | |||||
A curated package set and set of tools that let you build Haskell packages so they can run on a variety of platforms. reflex-platform is built on top of the nix package manager. | ||||||||||
Motion | 657 | 2 months ago | 14 | March 11, 2021 | 8 | mit | Ruby | |||
Reactive frontend UI components for Rails in pure Ruby | ||||||||||
Dom Expressions | 651 | 16 | 18 | 19 hours ago | 301 | July 15, 2022 | 22 | mit | JavaScript | |
A Fine-Grained Runtime for Performant DOM Rendering | ||||||||||
Blaze | 510 | 248 | 4 months ago | 15 | October 04, 2016 | 25 | other | JavaScript | ||
:fire: Meteor Blaze is a powerful library for creating live-updating user interfaces |
use leptos::*;
#[component]
pub fn SimpleCounter(cx: Scope, initial_value: i32) -> impl IntoView {
// create a reactive signal with the initial value
let (value, set_value) = create_signal(cx, initial_value);
// create event handlers for our buttons
// note that `value` and `set_value` are `Copy`, so it's super easy to move them into closures
let clear = move |_| set_value(0);
let decrement = move |_| set_value.update(|value| *value -= 1);
let increment = move |_| set_value.update(|value| *value += 1);
// create user interfaces with the declarative `view!` macro
view! {
cx,
<div>
<button on:click=clear>"Clear"</button>
<button on:click=decrement>"-1"</button>
<span>"Value: " {value} "!"</span>
<button on:click=increment>"+1"</button>
</div>
}
}
// Easy to use with Trunk (trunkrs.dev) or with a simple wasm-bindgen setup
pub fn main() {
mount_to_body(|cx| view! { cx, <SimpleCounter initial_value=3 /> })
}
Leptos is a full-stack, isomorphic Rust web framework leveraging fine-grained reactivity to build declarative user interfaces.
Resource
s) and HTML (out-of-order streaming of <Suspense/>
components.)Here are some resources for learning more about Leptos:
nightly
NoteMost of the examples assume youre using nightly
Rust.
To set up your Rust toolchain using nightly
(and add the ability to compile Rust to WebAssembly, if you havent already)
rustup toolchain install nightly
rustup default nightly
rustup target add wasm32-unknown-unknown
If youre on stable
, note the following:
"stable"
flag in Cargo.toml
: leptos = { version = "0.2", features = ["stable"] }
nightly
enables the function call syntax for accessing and setting signals. If youre using stable
,
youll just call .get()
, .set()
, or .update()
manually. Check out the
counters_stable
example
for examples of the correct API.cargo-leptos
cargo-leptos
is a build tool that's designed to make it easy to build apps that run on both the client and the server, with seamless integration. The best way to get started with a real Leptos project right now is to use cargo-leptos
and our starter template.
cargo install cargo-leptos
cargo leptos new --git https://github.com/leptos-rs/start
cd [your project name]
cargo leptos watch
Open browser on http://localhost:3000/
Leptos () is an ancient Greek word meaning thin, light, refine, fine-grained. To me, a classicist and not a dog owner, it evokes the lightweight reactive system that powers the framework. I've since learned the same word is at the root of the medical term leptospirosis, a blood infection that affects humans and animals... My bad. No dogs were harmed in the creation of this framework.
People usually mean one of three things by this question.
With 0.1 the APIs are basically settled. Were adding new features, but were very happy with where the type system and patterns have landed. I would not expect major breaking changes to your code to adapt to, for example, a 0.2.0 release.
Yes, Im sure there are. You can see from the state of our issue tracker over time that there arent that many bugs and theyre usually resolved pretty quickly. But for sure, there may be moments where you encounter something that requires a fix at the framework level, which may not be immediately resolved.
This may be the big one: production ready implies a certain orientation to a library: that you can basically use it, without any special knowledge of its internals or ability to contribute. Everyone has this at some level in their stack: for example I (@gbj) dont have the capacity or knowledge to contribute to something like wasm-bindgen
at this point: I simply rely on it to work.
There are several people in this community using Leptos right now for internal apps at work, who have also become significant contributors. I think this is the right level of production use for now. There may be missing features that you need, and you may end up building them! But for internal apps, if youre willing to build and contribute missing pieces along the way, the framework is definitely usable right now.
Sure! Obviously the view
macro is for generating DOM nodes but you can use the reactive system to drive native any GUI toolkit that uses the same kind of object-oriented, event-callback-based framework as the DOM pretty easily. The principles are the same:
I've put together a very simple GTK example so you can see what I mean.
On the surface level, these libraries may seem similar. Yew is, of course, the most mature Rust library for web UI development and has a huge ecosystem. Dioxus is similar in many ways, being heavily inspired by React. Here are some conceptual differences between Leptos and these frameworks:
Conceptually, these two frameworks are very similar: because both are built on fine-grained reactivity, most apps will end up looking very similar between the two, and Sycamore or Leptos apps will both look a lot like SolidJS apps, in the same way that Yew or Dioxus can look a lot like React.
There are some practical differences that make a significant difference:
Maturity: Sycamore is obviously a much more mature and stable library with a larger ecosystem.
Templating: Leptos uses a JSX-like template format (built on syn-rsx) for its view
macro. Sycamore offers the choice of its own templating DSL or a builder syntax.
Read-write segregation: Leptos, like Solid, encourages read-write segregation between signal getters and setters, so you end up accessing signals with tuples like let (count, set_count) = create_signal(cx, 0);
(If you prefer or if it's more convenient for your API, you can use create_rw_signal
to give a unified read/write signal.)
Signals are functions: In Leptos, you can call a signal to access it rather than calling a specific method (so, count()
instead of count.get()
) This creates a more consistent mental model: accessing a reactive value is always a matter of calling a function. For example:
let (count, set_count) = create_signal(cx, 0); // a signal
let double_count = move || count() * 2; // a derived signal
let memoized_count = create_memo(cx, move |_| count() * 3); // a memo
// all are accessed by calling them
assert_eq!(count(), 0);
assert_eq!(double_count(), 0);
assert_eq!(memoized_count(), 0);
// this function can accept any of those signals
fn do_work_on_signal(my_signal: impl Fn() -> i32) { ... }
Signals and scopes are 'static
: Both Leptos and Sycamore ease the pain of moving signals in closures (in particular, event listeners) by making them Copy
, to avoid the { let count = count.clone(); move |_| ... }
that's very familiar in Rust UI code. Sycamore does this by using bump allocation to tie the lifetimes of its signals to its scopes: since references are Copy
, &'a Signal<T>
can be moved into a closure. Leptos does this by using arena allocation and passing around indices: types like ReadSignal<T>
, WriteSignal<T>
, and Memo<T>
are actually wrappers for indices into an arena. This means that both scopes and signals are both Copy
and 'static
in Leptos, which means that they can be moved easily into closures without adding lifetime complexity.