1. Project Overview & Quickstart (yewstack/yew)
File: README.md
About
Yew is a modern Rust framework for creating multi-threaded, front-end web apps with WebAssembly.
- Features a macro for declaring interactive HTML with Rust expressions. Developers who have experience using JSX in React should feel quite at home when using Yew.
- Achieves high performance by minimizing DOM API calls for each page render and by making it easy to offload processing to background web workers.
- Supports JavaScript interoperability, allowing developers to leverage NPM packages and integrate with existing JavaScript applications.
Yew is named after a type of evergreen tree, and is pronounced /juห/. Entry with audio on Cambridge Dictionary.
Contributing
Yew is a community-driven effort and we welcome all kinds of contributions, big or small, from developers of all backgrounds. We want the Yew community to be a fun and friendly place, so please review our Code of Conduct to learn what behavior will not be tolerated.
๐ค New to Yew?
Start learning about the framework by helping us improve our documentation. Pull requests which improve test coverage are also very welcome.
๐ Looking for inspiration?
Check out the community curated list of awesome things related to Yew / WebAssembly at jetli/awesome-yew.
๐ค Confused about something?
Feel free to drop into our Discord chatroom or open a new "Question" issue to get help from contributors. Often questions lead to improvements to the ergonomics of the framework, better documentation and even new features!
๐ Ready to dive into the code?
After reviewing the Contribution Guide, check out the "Good First Issues" (they are eager for attention!). Once you find one that interests you, feel free to assign yourself to an issue and don't hesitate to reach out for guidance, the issues vary in complexity.
๐ฑ Found a bug?
Please report all bugs! We are happy to help support developers fix the bugs they find if they are interested and have the time.
Contributors
Code Contributors
This project exists thanks to all the people who contribute.
Financial Contributors
Become a financial contributor and help us sustain our community. [Contribute]
Individuals
Organizations
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
File: examples/async_clock/README.md
Asynchronous coding in Yew
An example of using asynchronous tasks in a component. This example creates a clock in the background and
continuously awaits clock-ticks. When the clock updates the new time is sent to the UI component to display.
In parallel it fetches online jokes to make the clock more entertaining to watch.
Its main purpose is to demonstrate various ways of using async code in a yew component. It uses the following async
features:
- send_future
- send_stream
- spawn_local
- mpsc::unbounded channels
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/boids/README.md
Boids Example
A version of Boids implemented in Yew.
This example doesn't make use of a Canvas,
instead, each boid has its own element demonstrating the performance of Yew's virtual DOM.
Concepts
The example uses gloo::timers implementation of setInterval to drive the Yew game loop.
Improvements
- Add the possibility to switch the behaviour from flocking to scattering by inverting the cohesion rule so that boids avoid each other.
This should also invert the color adaption to restore some variety. - Add keyboard shortcuts for the actions.
- Make it possible to hide the settings panel entirely
- Bigger boids should accelerate slower than smaller ones
- Share settings by encoding them into the URL
- Resize the boids when "Spacing" is changed.
The setting should then also be renamed to something like "Size".
Running
Run this application with the trunk development server:
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' trunk serve --openFile: examples/communication_child_to_parent/README.md
Child-to-Parent Example
A simple example of updating a parent from two children using a callback mechanism.
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/communication_grandchild_with_grandparent/README.md
Grandchild-with-Grandparent Example
A simple example of updating a grandparent component from two grandchildren using a callback passed down using the context API.
The grandchildren themselves also update whenever the grandparent updates the shared state.
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/communication_grandparent_to_grandchild/README.md
Grandparent-to-Grandchild Example
A simple example of updating a grandchild component from a grandparent using a shared state through the ContextProvider.
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/communication_parent_to_child/README.md
Parent-to-Child Example
A simple example of updating a child from a parent using properties
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/contexts/README.md
Context Example
This is currently a technical demonstration of Context API.
Concepts
The example has two components, which communicates through a context
as opposed to the traditional method using component links.
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/counter/README.md
Counter Example
A simple example of a counter which can be increased or decreased with the press of a button.
Concepts
Demonstrates the use of messages to update state.
Running
Run this application with the trunk development server:
trunk serve --openFile: examples/counter_functional/README.md
Counter Example
A simple example of a counter which can be increased or decreased with the press of a button implemented using function components
Concepts
Demonstrates the use of function components.
Running
Run this application with the trunk development server:
trunk serve --open2. Official Technical Reference & Guides (yewstack/docs)
File: README.md
THIS REPOSITORY HAS BEEN MERGED INTO https://github.com/yewstack/yew
PLEASE SUBMIT ALL PRs AND ISSUES THERE (NOT HERE)
Building the book locally
Note that Yew uses Gitbook which renders differently from mdbook. However the latest Gitbook is
not compatible with gitbook-cli :(
Install mdbook:
$ cargo install mdbookRender and view the book:
$ mdbook serveFile: src/getting-started/project-setup/README.md
Project Setup
Rust
First, you'll need Rust. To install Rust and the cargo build tool, follow the official instructions.
**Wasm Build Tools**
Extra tooling is needed to facilitate the interop between WebAssembly and JavaScript. Additionally, depending on the tool you choose, they can help make deployment and packaging much less of a headache by generating all of the wrapper JavaScript code necessary to run the .wasm file from your app in the browser.
[**`wasm-pack`**](https://rustwasm.github.io/docs/wasm-pack/)
A CLI tool developed by the Rust / Wasm Working Group for packaging up WebAssembly. Best used together with the wasm-pack-plugin for Webpack.
{% page-ref page="using-wasm-pack.md" %}
[**`wasm-bindgen`**](https://rustwasm.github.io/docs/wasm-bindgen/)
Both a library and CLI tool and is also developed by the Rust / Wasm Working Group. It is a low level tool (used internally by wasm-pack) which facilitates JS / WebAssembly interoperability. We don't recommend using wasm-bindgendirectly because it requires hand-writing some JavaScript to bootstrap your WebAssembly binary. However, it is possible and more info can be found on the wasm-bindgen guide.
{% page-ref page="using-wasm-bindgen.md" %}
[**`cargo-web`**](https://github.com/koute/cargo-web)
The preferred web workflow tool before the introduction of wasm-pack and wasm-bindgen. It is still the quickest way to get up and running and worth installing to run examples that haven't been migrated to support wasm-pack yet.
{% page-ref page="using-cargo-web.md" %}
Comparison
wasm-pack |
wasm-bindgen |
cargo-web |
|
|---|---|---|---|
| Project Status | Actively maintained by the Rust / Wasm Working Group | Actively maintained by the Rust / Wasm Working Group | No Github activity for over 6 months |
| Dev Experience | Almost there! Requires webpack for best experience. |
Barebones. You'll need to write some scripts to streamline your dev |
experience. | Just works! Batteries included, no external dependencies needed. || Local Server | Supported with webpack plugin | Not supported | Supported |
| Auto rebuild on local changes | Supported with webpack plugin | Not Supported | Supported |
| Headless Browser Testing | Supported | Supported | Supported |
| Supported Targets | wasm32-unknown-unknown | wasm32-unknown-unknown | wasm32-unknown-unknown
`wasm32-unknown-emscripten`
`asmjs-unknown-emscripten` || web-sys | Compatible | Compatible | Incompatible |
| stdweb | Compatible | Compatible | Compatible |
| Example Usage | Starter template | Build script for
Yew examples | Build script for
Yew examples |
File: src/concepts/components/README.md
Components
What are Components?
Components are the building blocks of Yew. They manage their own state and can render themselves to the DOM. Components are created by implementing the Component trait which describes the lifecycle of a component.
Lifecycle
{% hint style="info" %}Contribute to our docs: Add a diagram of the component lifecycle
{% endhint %}
Lifecycle Methods
Create
When a component is created, it receives properties from its parent component as well as a ComponentLink. The properties can be used to initialize the component's state and the "link" can be used to register callbacks or send messages to the component.
It is common to store the props and the link in your component struct, like so:
pub struct MyComponent {
props: Props,
link: ComponentLink<Self>,
}
impl Component for MyComponent {
type Properties = Props;
// ...
fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
MyComponent { props, link }
}
// ...
}View
Components declare their layout in the view() method. Yew provides the html! macro for declaring HTML and SVG nodes and their listeners as well as child components. The macro acts a lot like React's JSX, but uses Rust expressions instead of JavaScript.
impl Component for MyComponent {
// ...
fn view(&self) -> Html {
let onclick = self.link.callback(|_| Msg::Click);
html! {
{ self.props.button_text }
}
}
}For usage details, check out the html! guide:
{% page-ref page="../html/" %}
Rendered
The rendered() component lifecycle method is called after view() is processed and Yew has rendered your component, but before the browser refreshes the page. A component may wish to implement this method to perform actions that can only be done after the component has rendered elements. You can check whether this is the first time the component was rendered via the first_render parameter.
use stdweb::web::html_element::InputElement;
use stdweb::web::IHtmlElement;
use yew::prelude::*;
pub struct MyComponent {
node_ref: NodeRef,
}
impl Component for MyComponent {
// ...
fn view(&self) -> Html {
html! {
}
}
fn rendered(&mut self, first_render: bool) {
if first_render {
if let Some(input) = self.node_ref.try_into::() {
input.focus();
}
}
}
}{% hint style="info" %}
Note that this lifecycle method does not require an implementation and will do nothing by default
{% endhint %}
Update
Components are dynamic and can register to receive asynchronous messages. The update() lifecycle method is called for each message. This allows the component to update itself based on what the message was, and determine if it needs to re-render itself. Messages can be triggered by HTML elements listeners or be sent by child components, Agents, Services, or Futures.
Here's an example of what update() could look like:
pub enum Msg {
SetInputEnabled(bool)
}
impl Component for MyComponent {
type Message = Msg;
// ...
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SetInputEnabled(enabled) => {
if self.input_enabled != enabled {
self.input_enabled = enabled;
true // Re-render
} else {
false
}
}
}
}
}Change
Components may be re-rendered by their parents. When this happens, they could receive new properties and choose to re-render. This design facilitates parent to child component communication through changed properties.
A typical implementation would look like:
impl Component for MyComponent {
// ...
fn change(&mut self, props: Self::Properties) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
}Destroy
After Components are unmounted from the DOM, Yew calls the destroy() lifecycle method to support any necessary clean up operations. This method is optional and does nothing by default.
Associated Types
The Component trait has two associated types: Message and Properties.
impl Component for MyComponent {
type Message = Msg;
type Properties = Props;
// ...
}Message represents a variety of messages that can be processed by the component to trigger some side effect. For example, you may have a Click message which triggers an API request or toggles the appearance of a UI component. It is common practice to create an enum called Msg in your component's module and use that as the message type in the component. It is common to shorten "message" to "msg".
enum Msg {
Click,
}Properties represents the information passed to a component from its parent. This type must implements the Properties trait (usually by deriving it) and can specify whether certain properties are required or optional. This type is used when creating and updating a component. It is common practice to create a struct called Props in your component's module and use that as the component's Properties type. It is common to shorten "properties" to "props". Since props are handed down from parent components, the root component of your application typically has a Properties type of (). If you wish to specify properties for your root component, use the App::mount_with_props method.
File: src/concepts/html/README.md
Using html!
The html! macro allows you to write HTML and SVG code declaratively. It is similar to JSX (a Javascript extension which allows you to write HTML-like code inside of Javascript).
Important notes
The
html!macro only accepts one root html node (you can counteract this byAn empty
html! {}invocation is valid and will not render anythingLiterals must always be quoted and wrapped in braces:
html! { "Hello, World" }
{% hint style="info" %}
The html! macro can reach easily the default recursion limit of the compiler. It is advised to bump its value if you encounter compilation errors. Use an attribute like `# and this Stack Overflow question for details.
{% endhint %}
{% page-ref page="lists.md" %}
{% page-ref page="elements.md" %}
{% page-ref page="literals-and-expressions.md" %}
{% page-ref page="components.md" %}
File: src/README.md
Introduction
What is Yew?
Yew is a modern Rust framework for creating multi-threaded front-end web apps with WebAssembly.
- It features a component-based framework which makes it easy to create interactive UIs. Developers who have experience with frameworks like React and Elm should feel quite at home when using Yew.
- It has great performance by minimizing DOM API calls and by helping developers easily offload processing to background web workers.
- It supports JavaScript interoperability, allowing developers to leverage NPM packages and integrate with existing JavaScript applications.
Join Us ๐
- You can report bugs and discuss features on the GitHub issues page
- We โค๏ธ pull requests. Check out good first issues if you'd like to help out!
- Our Discord chat is very active and is a great place to ask questions
Ready to dive in?
Click the link below to learn how to build your first Yew app and learn from community example projects
{% page-ref page="getting-started/project-setup/" %}
**Still not convinced?**
This project is built on cutting edge technology and is great for developers who like to develop the foundational projects of tomorrow. Here are some reasons why we believe that frameworks like Yew are the future of web development.
**Wait, why WebAssembly?**
WebAssembly (Wasm) is a portable low-level language that Rust can compile into. It runs at native speeds in the browser and is interoperable with JavaScript and supported in all major browsers. For ideas on how to get the most out of WebAssembly for your app, check out this list of Use Cases.
It should be noted that using Wasm is not (yet) a silver bullet for improving the performance of a web app. As of right now, using DOM APIs from WebAssembly is still slower than calling them directly from JavaScript. This is a temporary issue which the WebAssembly Interface Types proposal aims to resolve. If you would like to learn more, check out this excellent article from Mozilla.
Ok, but why Rust?
Rust is blazing fast and reliable with its rich type system and ownership model. It has a tough learning curve but is well worth the effort. Rust has been voted the most loved programming language in Stack Overflow's Developer Survey five years in a row: 2016, 2017, 2018, 2019 and 2020.
Rust also helps developers write safer code with its rich type system and ownership model. Say goodbye to hard to track down race condition bugs in JavaScript! In fact, with Rust, most of your bugs will be caught by the compiler before your app even runs. And don't worry, when your app does run into an error, you can still get full stack-traces for your Rust code in the browser console.
Alternatives?
We love to share ideas with other projects and believe we can all help each other reach the full potential of this exciting new technology. If you're not into Yew, you may like the following projects: