gloo
A modular toolkit for building fast, reliable Web applications and libraries with Rust and WASM
Top Related Projects
Rust / Wasm framework for creating reliable and efficient web applications
A Rust framework for creating web apps
A standard library for the client-side Web
Facilitating high-level interactions between Wasm modules and JavaScript
📦✨ your favorite rust -> wasm workflow tool!
Build fast web applications with Rust.
Quick Overview
Gloo is a modular toolkit for building fast and reliable Web applications with Rust and WebAssembly. It provides a collection of libraries that simplify common tasks in web development, such as DOM manipulation, event handling, and AJAX requests, while leveraging Rust's performance and safety features.
Pros
- Improves performance of web applications by utilizing Rust and WebAssembly
- Provides a modular approach, allowing developers to use only the components they need
- Offers type-safe bindings to Web APIs, reducing runtime errors
- Seamlessly integrates with existing JavaScript ecosystems
Cons
- Steeper learning curve for developers not familiar with Rust
- Limited ecosystem compared to more established JavaScript frameworks
- May require additional build steps and tooling setup
- Performance gains might be less noticeable for simple applications
Code Examples
- Creating an element and appending it to the body:
use gloo::utils::document;
use wasm_bindgen::JsCast;
let p = document()
.create_element("p")
.unwrap()
.dyn_into::<web_sys::HtmlElement>()
.unwrap();
p.set_inner_text("Hello, Gloo!");
document().body().unwrap().append_child(&p).unwrap();
- Adding an event listener to a button:
use gloo::events::EventListener;
use web_sys::HtmlElement;
let button: HtmlElement = // ... obtain button element
let listener = EventListener::new(&button, "click", move |_event| {
web_sys::console::log_1(&"Button clicked!".into());
});
- Making an HTTP request using Gloo's futures:
use gloo::net::http::Request;
let response = Request::get("https://api.example.com/data")
.send()
.await
.unwrap();
let json: serde_json::Value = response.json().await.unwrap();
web_sys::console::log_1(&format!("Received data: {:?}", json).into());
Getting Started
To start using Gloo in your Rust WebAssembly project:
-
Add Gloo to your
Cargo.toml
:[dependencies] gloo = "0.8"
-
Import and use Gloo modules in your Rust code:
use gloo::utils::document; use gloo::events::EventListener; use gloo::net::http::Request; // Your application code here
-
Build your project with
wasm-pack build
and integrate the resulting WebAssembly module into your web application.
Competitor Comparisons
Rust / Wasm framework for creating reliable and efficient web applications
Pros of Yew
- More comprehensive framework for building client-side web apps
- Provides a component-based architecture similar to React
- Offers a rich ecosystem with additional libraries and tools
Cons of Yew
- Steeper learning curve due to its more complex architecture
- Potentially larger bundle sizes for smaller applications
- May be overkill for simple web interactions
Code Comparison
Yew example:
use yew::prelude::*;
#[function_component(App)]
fn app() -> Html {
let counter = use_state(|| 0);
let onclick = {
let counter = counter.clone();
Callback::from(move |_| counter.set(*counter + 1))
};
html! {
<div>
<button {onclick}>{ "+1" }</button>
<p>{ *counter }</p>
</div>
}
}
Gloo example:
use gloo::events::EventListener;
use wasm_bindgen::JsCast;
use web_sys::{Element, HtmlElement};
let document = web_sys::window().unwrap().document().unwrap();
let button: Element = document.create_element("button").unwrap();
button.set_inner_html("+1");
let p: Element = document.create_element("p").unwrap();
p.set_inner_html("0");
EventListener::new(&button, "click", move |_event| {
let count: i32 = p.inner_html().parse().unwrap();
p.set_inner_html(&(count + 1).to_string());
}).forget();
A Rust framework for creating web apps
Pros of Seed
- Higher-level framework for building web applications
- Provides a more opinionated structure and architecture
- Includes built-in state management and routing capabilities
Cons of Seed
- Less flexible for low-level DOM manipulation
- Steeper learning curve for developers new to Rust and web development
- More limited ecosystem compared to Gloo's broader approach
Code Comparison
Seed example:
#[update]
fn increment(model: &mut Model) {
model.counter += 1;
}
#[view]
fn view(model: &Model) -> Node<Msg> {
button![model.counter, ev(Ev::Click, |_| Msg::Increment)]
}
Gloo example:
let button = document.create_element("button")?;
button.set_inner_html(&format!("Count: {}", count));
button.add_event_listener(move |_: Event| {
count += 1;
button.set_inner_html(&format!("Count: {}", count));
});
Seed provides a more declarative approach with built-in state management, while Gloo offers lower-level control over DOM manipulation. Seed is better suited for larger applications with complex state management needs, whereas Gloo is more flexible for integrating with existing JavaScript libraries or creating custom components.
A standard library for the client-side Web
Pros of stdweb
- More mature and established project with a longer history
- Provides a higher-level abstraction for DOM manipulation
- Offers a wider range of built-in JavaScript bindings
Cons of stdweb
- Less actively maintained compared to gloo
- Larger bundle sizes due to more comprehensive bindings
- May have more overhead for simple use cases
Code Comparison
stdweb example:
use stdweb::web::document;
use stdweb::web::IParentNode;
fn main() {
let element = document().query_selector("#my-element").unwrap();
element.set_text_content("Hello from stdweb!");
}
gloo example:
use gloo_utils::document;
use wasm_bindgen::JsCast;
fn main() {
let element = document().get_element_by_id("my-element").unwrap();
element.dyn_ref::<web_sys::HtmlElement>().unwrap().set_inner_text("Hello from gloo!");
}
Both stdweb and gloo are Rust libraries for WebAssembly development, providing bindings to web APIs. stdweb offers a more comprehensive set of bindings and a higher-level abstraction, while gloo focuses on a more modular approach with lower-level bindings. gloo is part of the rustwasm organization and is more actively maintained, making it a better choice for new projects. stdweb may be preferred for existing projects or those requiring extensive DOM manipulation.
Facilitating high-level interactions between Wasm modules and JavaScript
Pros of wasm-bindgen
- More comprehensive and lower-level bindings for Rust-WASM interop
- Wider adoption and community support
- Supports generating TypeScript definitions
Cons of wasm-bindgen
- Steeper learning curve for beginners
- More verbose code for simple use cases
- Requires additional setup and configuration
Code Comparison
wasm-bindgen:
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
gloo:
use gloo_utils::format::JsValueSerdeExt;
pub fn greet(name: &JsValue) -> JsValue {
format!("Hello, {}!", name.as_string().unwrap()).into()
}
Summary
wasm-bindgen provides more comprehensive bindings and wider adoption, but can be more complex for simple use cases. gloo offers a higher-level abstraction, making it easier for beginners but potentially limiting for advanced scenarios. wasm-bindgen is better suited for large-scale projects with complex interop requirements, while gloo shines in smaller projects or when rapid development is prioritized. The choice between the two depends on the specific needs of the project and the developer's familiarity with Rust and WebAssembly concepts.
📦✨ your favorite rust -> wasm workflow tool!
Pros of wasm-pack
- Focused specifically on packaging and publishing Rust-generated WebAssembly
- Provides a streamlined workflow for creating and managing wasm projects
- Integrates well with npm for easy distribution of wasm modules
Cons of wasm-pack
- More limited in scope compared to gloo's broader ecosystem
- Less flexibility for low-level wasm operations and browser API interactions
- Smaller community and fewer extensions/plugins available
Code Comparison
wasm-pack example:
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
gloo example:
use gloo_utils::document;
let element = document().create_element("div")?;
element.set_inner_html("Hello, World!");
Summary
wasm-pack is a specialized tool for packaging and publishing Rust-generated WebAssembly, offering a streamlined workflow for wasm projects. It integrates well with npm but has a more limited scope compared to gloo.
gloo, on the other hand, provides a broader ecosystem of tools and utilities for working with WebAssembly and browser APIs. It offers more flexibility for low-level wasm operations and has a larger community, but may require more setup for simple packaging tasks.
Choose wasm-pack for straightforward wasm packaging and publishing, or gloo for more comprehensive wasm development with broader browser integration capabilities.
Build fast web applications with Rust.
Pros of Leptos
- Full-featured web framework with reactive state management and server-side rendering
- Integrates well with existing Rust ecosystems and tools
- Offers a more opinionated and structured approach to building web applications
Cons of Leptos
- Steeper learning curve for developers new to reactive programming concepts
- Less flexibility compared to Gloo's low-level approach
- Smaller community and ecosystem compared to more established frameworks
Code Comparison
Leptos example:
#[component]
fn Counter(cx: Scope, initial_value: i32) -> impl IntoView {
let (count, set_count) = create_signal(cx, initial_value);
view! { cx,
<button on:click=move |_| set_count.update(|count| *count += 1)>
"Count: {count}"
</button>
}
}
Gloo example (using web-sys):
use gloo_events::EventListener;
use web_sys::{Element, HtmlButtonElement};
let button: HtmlButtonElement = // ... obtain button element
let mut count = 0;
let listener = EventListener::new(&button, "click", move |_event| {
count += 1;
button.set_text_content(Some(&format!("Count: {}", count)));
});
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Gloo
A toolkit for building fast, reliable Web applications and libraries with Rust and Wasm.
What?
Gloo is a collection of libraries, and those libraries provide ergonomic Rust
wrappers for browser APIs. web-sys
/js-sys
are very difficult/inconvenient
to use directly so gloo provides wrappers around the raw bindngs which makes it easier
to consume those APIs. This is why it is called a "toolkit", instead of "library"
or "framework".
Background
In the Rust and WebAssembly working group's 2019 roadmap, we chose to deliberately cultivate our library ecosystem by building a modular toolkit:
Collaborating on a Modular Toolkit
The idea of building [high-level libraries] in a modular way that will allow others in the community to put the components together in a different way is very exciting to me. This hopefully will make the ecosystem as a whole much stronger.
In particular Iâd love to see a modular effort towards implementing a virtual DOM library with JSX like syntax. There have been several efforts on this front but all have seemed relatively monolithic and âbatteries includedâ. I hope this will change in 2019.
— Ryan Levick in Rust WebAssembly 2019
Don't create branded silos. Branding might perhaps be useful to achieve fame. But if we truly want Rust's Wasm story to succeed we should think of ways to collaborate instead of carving out territory.
— Yoshua Wuyts in Wasm 2019
In 2018, we created foundational libraries like
js-sys
andweb-sys
. In 2019, we should build modular, high-level libraries on top of them, and collect the libraries under an umbrella toolkit crate for a holistic experience. This toolkit and its libraries will make available all the batteries you want when targeting Wasm.Building a greenfield Web application? Use the whole toolkit to hit the ground running. Carefully crafting a tiny Wasm module and integrating it back into an existing JavaScript project? Grab that one targeted library you need out from the toolkit and use it by itself.
Gloo is this modular toolkit.
Goals
-
Support both whole Web applications and small, targeted libraries: Gloo, and the collection of utility crates that make up its toolkit, should help you be productive if you are writing a green-field web application with Rust and Wasm. And it should also help you be productive if you are writing a small, targeted Wasm library that will be integrated into an existing JavaScript application.
-
Cultivate the Rust and Wasm library ecosystem: We want to use Gloo as a forcing function for creating and sharing the building blocks of Web development. The kinds of libraries that any framework or high-level library would need to build. We want to explicitly disentangle these libraries and make them available for sharing across the whole ecosystem.
-
Modular Toolkit, not Framework: Gloo should be a loose collection of utility crates that can be used individually, or all together. Gloo doesn't assume that it "owns" the whole Webpage, that it controls the Wasm
start
function, etc. This lack of assumptions enables reaching more use cases (such as surgically replacing a hot code path from JS) than monolithic frameworks can. Wherever possible, Gloo should prefer interfaces over implementations, so that different implementations with different approaches are swap-able. -
Fast: Let's leverage Rust's zero-cost abstractions, and design with performance in mind, to show everyone how fast the Web can be ;)
-
Reliable: Every crate should be thoroughly tested. Headless browser tests. Quickcheck tests. Using the type system to make whole classes of bugs impossible.
-
Small: Small code size for faster page loads. No accidentally pulling in all of the panicking and formatting infrastructure. Users shouldn't have to make a trade off between using Gloo libraries and having small Wasm binaries.
-
Idiomatic: We want to build Rust-y APIs, that feel natural to use. The Web's APIs were not designed for the Rust language, and you can feel the impedance mismatch every now and then. Let's correct that, bridge the gap, and make libraries that are a joy to use.
Example
This example uses gloo::events
for adding event listeners and gloo::timers
for creating timeouts. It creates a <button>
element and adds a "click" event
listener to it. Whenever the button is clicked, it starts a one second timeout,
which sets the button's text content to "Hello from one second ago!".
use gloo::{events::EventListener, timers::callback::Timeout};
use wasm_bindgen::prelude::*;
pub struct DelayedHelloButton {
button: web_sys::Element,
on_click: events::EventListener,
}
impl DelayedHelloButton {
pub fn new(document: &web_sys::Document) -> Result<DelayedHelloButton, JsValue> {
// Create a `<button>` element.
let button = document.create_element("button")?;
// Listen to "click" events on the button.
let button2 = button.clone();
let on_click = EventListener::new(&button, "click", move |_event| {
// After a one second timeout, update the button's text content.
let button3 = button2.clone();
Timeout::new(1_000, move || {
button3.set_text_content(Some("Hello from one second ago!"));
})
.forget();
});
Ok(DelayedHelloButton { button, on_click })
}
}
Get Involved!
Want to help us build Gloo? Check out CONTRIBUTING.md
!
Top Related Projects
Rust / Wasm framework for creating reliable and efficient web applications
A Rust framework for creating web apps
A standard library for the client-side Web
Facilitating high-level interactions between Wasm modules and JavaScript
📦✨ your favorite rust -> wasm workflow tool!
Build fast web applications with Rust.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot