yew Documentation

Rust / Wasm framework for creating reliable and efficient web applications

32,784 stars Rust Rust 1 file ยท ~5,719 tokens #asmjs#concurrency#elm#emscripten#gui#hacktoberfest#jsx#multithreading
RAW Doc

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:

bash
trunk serve --open

File: 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:

bash
RUSTFLAGS='--cfg getrandom_backend="wasm_js"' trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

File: 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:

bash
trunk serve --open

2. 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:

bash
$ cargo install mdbook

Render and view the book:

bash
$ mdbook serve

File: 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
text
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

text
`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:

rust
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.

rust
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.

rust
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:

rust
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:

rust
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.

rust
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".

rust
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

  1. The html! macro only accepts one root html node (you can counteract this by

    using fragments or iterators)

  2. An empty html! {} invocation is valid and will not render anything

  3. Literals 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 ๐Ÿ˜Š

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:

  • Percy - "A modular toolkit for building isomorphic web apps with Rust + WebAssembly"
  • Seed - "A Rust framework for creating web apps"