GitBook: [master] 29 pages modified

This commit is contained in:
Justin Starry 2020-07-05 15:50:58 +00:00 committed by Justin Starry
parent 5c3a71713c
commit 6042da816a
23 changed files with 198 additions and 343 deletions

View File

@ -6,13 +6,9 @@ description: Make your app faster
## neq\_assign
When a component receives props from its parent component, the `change` method is called. This, in
addition to allowing you to update the component's state, also allows you to return a `ShouldRender`
boolean value that indicates if the component should re-render itself in response to the prop changes.
When a component receives props from its parent component, the `change` method is called. This, in addition to allowing you to update the component's state, also allows you to return a `ShouldRender` boolean value that indicates if the component should re-render itself in response to the prop changes.
Re-rendering is expensive, and if you can avoid it, you should. As a general rule, you only want to
re-render when the props actually changed. The following block of code represents this rule,
returning `true` if the props differed from the previous props:
Re-rendering is expensive, and if you can avoid it, you should. As a general rule, you only want to re-render when the props actually changed. The following block of code represents this rule, returning `true` if the props differed from the previous props:
```rust
use yew::ShouldRender;
@ -36,68 +32,37 @@ impl Example {
}
```
But we can go further! This is six lines of boilerplate can be reduced down to one by using a trait
and a blanket implementation for anything that implements `PartialEq`. Check out the `yewtil` crate's
`NeqAssign` trait [here](https://docs.rs/yewtil/*/yewtil/trait.NeqAssign.html).
But we can go further! This is six lines of boilerplate can be reduced down to one by using a trait and a blanket implementation for anything that implements `PartialEq`. Check out the `yewtil` crate's `NeqAssign` trait [here](https://docs.rs/yewtil/*/yewtil/trait.NeqAssign.html).
## RC
In an effort to avoid cloning large chunks of data to create props when re-rendering, we can use
smart pointers to only clone the pointer instead. If you use `Rc<_>`s in your props and child
components instead of plain unboxed values, you can delay cloning until you need to modify the data
in the child component, where you use `Rc::make_mut` to clone and get a mutable reference to the data
you want to alter. By not cloning until mutation, child components can reject props identical to
their state-owned props in `Component::change` for almost no performance cost, versus the case where
the data itself needs to be copied into the props struct in the parent before it is compared and
rejected in the child.
In an effort to avoid cloning large chunks of data to create props when re-rendering, we can use smart pointers to only clone the pointer instead. If you use `Rc<_>`s in your props and child components instead of plain unboxed values, you can delay cloning until you need to modify the data in the child component, where you use `Rc::make_mut` to clone and get a mutable reference to the data you want to alter. By not cloning until mutation, child components can reject props identical to their state-owned props in `Component::change` for almost no performance cost, versus the case where the data itself needs to be copied into the props struct in the parent before it is compared and rejected in the child.
This optimization is most useful for data types that aren't `Copy`. If you can copy your data easily,
then it probably isn't worth putting it behind a smart pointer. For structures that can contain lots
of data like `Vec`, `HashMap`, and `String`, this optimization should be worthwhile.
This optimization is most useful for data types that aren't `Copy`. If you can copy your data easily, then it probably isn't worth putting it behind a smart pointer. For structures that can contain lots of data like `Vec`, `HashMap`, and `String`, this optimization should be worthwhile.
This optimization works best if the values are never updated by the children, and even better, if
they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values in
for pure components.
This optimization works best if the values are never updated by the children, and even better, if they are rarely updated by parents. This makes `Rc<_>s` a good choice for wrapping property values in for pure components.
## View Functions
For code readability reasons, it often makes sense to migrate sections of `html!` to their own
functions so you can avoid the rightward drift present in deeply nested HTML.
For code readability reasons, it often makes sense to migrate sections of `html!` to their own functions so you can avoid the rightward drift present in deeply nested HTML.
## Pure Components/Function Components
Pure components are components that don't mutate their state, only displaying content and propagating
messages up to normal, mutable components. They differ from view functions in that they can be used
from within the `html!` macro using the component syntax \(`<SomePureComponent />`\) instead of
expression syntax \(`{some_view_function()}`\), and that depending on their implementation, they can
be memoized - preventing re-renders for identical props using the aforementioned `neq_assign` logic.
Pure components are components that don't mutate their state, only displaying content and propagating messages up to normal, mutable components. They differ from view functions in that they can be used from within the `html!` macro using the component syntax \(`<SomePureComponent />`\) instead of expression syntax \(`{some_view_function()}`\), and that depending on their implementation, they can be memoized - preventing re-renders for identical props using the aforementioned `neq_assign` logic.
Yew doesn't natively support pure or function components, but they are available via external crates.
Function components don't exist yet, but in theory, pure components could be generated by using proc
macros and annotating functions.
Function components don't exist yet, but in theory, pure components could be generated by using proc macros and annotating functions.
## Keyed DOM nodes when they arrive
## Compile speed optimizations using Cargo Workspaces
Arguably, the largest drawback to using Yew is the long time it takes to compile. Compile time seems
to correlate with the quantity of code found within `html!` macro blocks. This tends to not be a
significant problem for smaller projects, but for web apps that span multiple pages, it makes sense
to break apart your code across multiple crates to minimize the amount of work the compiler has to do
for each change made.
Arguably, the largest drawback to using Yew is the long time it takes to compile. Compile time seems to correlate with the quantity of code found within `html!` macro blocks. This tends to not be a significant problem for smaller projects, but for web apps that span multiple pages, it makes sense to break apart your code across multiple crates to minimize the amount of work the compiler has to do for each change made.
You should try to make your main crate handle routing/page selection, move all commonly shared code
to another crate, and then make a different crate for each page, where each page could be a different
component, or just a big function that produces `Html`. In the best case scenario, you go from
rebuilding all of your code on each compile to rebuilding only the main crate, and one of your page
crates. In the worst case, where you edit something in the "common" crate, you will be right back to
where you started: compiling all code that depends on that commonly shared crate, which is
probably everything else.
You should try to make your main crate handle routing/page selection, move all commonly shared code to another crate, and then make a different crate for each page, where each page could be a different component, or just a big function that produces `Html`. In the best case scenario, you go from rebuilding all of your code on each compile to rebuilding only the main crate, and one of your page crates. In the worst case, where you edit something in the "common" crate, you will be right back to where you started: compiling all code that depends on that commonly shared crate, which is probably everything else.
If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg. a
page that renders on top of another page\), you can use an example crate to create a more simple
implementation of the main page and render your work-in-progress component on top of that.
If your main crate is too heavyweight, or you want to rapidly iterate on a deeply nested page \(eg. a page that renders on top of another page\), you can use an example crate to create a more simple implementation of the main page and render your work-in-progress component on top of that.
## Build size optimization
@ -106,19 +71,13 @@ implementation of the main page and render your work-in-progress component on to
* `cargo.toml` \( defining release profile \)
* optimize wasm code using `wasm-opt`
More information about code size profiling:
[rustwasm book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
More information about code size profiling: [rustwasm book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
### wee\_alloc
[wee\_alloc](https://github.com/rustwasm/wee_alloc) is a tiny allocator that is much smaller than the
allocator that is normally used in Rust binaries. Replacing the default allocator with this one will
result in smaller WASM file sizes, at the expense of speed and memory overhead.
[wee\_alloc](https://github.com/rustwasm/wee_alloc) is a tiny allocator that is much smaller than the allocator that is normally used in Rust binaries. Replacing the default allocator with this one will result in smaller WASM file sizes, at the expense of speed and memory overhead.
The slower speed and memory overhead are minor in comparison to the size gains made by not including
the default allocator. This smaller file size means that your page will load faster, and so it is
generally recommended that you use this allocator over the default, unless your app is doing some
allocation-heavy work.
The slower speed and memory overhead are minor in comparison to the size gains made by not including the default allocator. This smaller file size means that your page will load faster, and so it is generally recommended that you use this allocator over the default, unless your app is doing some allocation-heavy work.
```rust
// Use `wee_alloc` as the global allocator.
@ -152,8 +111,7 @@ Further more it is possible to optimize size of `wasm` code.
wasm-opt info: [binaryen project](https://github.com/WebAssembly/binaryen)
The Rust Wasm book features a section about reducing the size of WASM binaries:
[Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)
The Rust Wasm book features a section about reducing the size of WASM binaries: [Shrinking .wasm size](https://rustwasm.github.io/book/game-of-life/code-size.html)
* using `wasm-pack` which by default optimizes `wasm` code in release builds
* using `wasm-opt` directly on `wasm` files.
@ -164,8 +122,7 @@ wasm-opt wasm_bg.wasm -Os -o wasm_bg_opt.wasm
#### Build size of 'minimal' example in yew/examples/
Note: `wasm-pack` combines optimization for Rust and Wasm code. `wasm-bindgen` is used in this
example without any Rust size optimization.
Note: `wasm-pack` combines optimization for Rust and Wasm code. `wasm-bindgen` is used in this example without any Rust size optimization.
| used tool | size |
| :--- | :--- |

View File

@ -4,16 +4,9 @@ description: Yew's Actor System
# Agents
Agents are similar to Angular's [Services](https://angular.io/guide/architecture-services) \(but
without dependency injection\), and provide a Yew with an
[Actor Model](https://en.wikipedia.org/wiki/Actor_model). Agents can be used to route messages
between components independently of where they sit in the component hierarchy, or they can be used to
create a shared state, and they can also be used to offload computationally expensive tasks from the
main thread which renders the UI. There is also planned support for using agents to allow Yew
applications to communicate across tabs \(in the future\).
Agents are similar to Angular's [Services](https://angular.io/guide/architecture-services) \(but without dependency injection\), and provide a Yew with an [Actor Model](https://en.wikipedia.org/wiki/Actor_model). Agents can be used to route messages between components independently of where they sit in the component hierarchy, or they can be used to create a shared state, and they can also be used to offload computationally expensive tasks from the main thread which renders the UI. There is also planned support for using agents to allow Yew applications to communicate across tabs \(in the future\).
In order for agents to run concurrently, Yew uses
[web-workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
In order for agents to run concurrently, Yew uses [web-workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
## Lifecycle
@ -24,12 +17,19 @@ In order for agents to run concurrently, Yew uses
#### Reaches
* Context - There will exist at most one instance of a Context Agent at any given time. Bridges will
spawn or connect to an already spawned agent on the UI thread. This can be used to coordinate state
between components or other agents. When no bridges are connected to this agent, the agent will
disappear.
spawn or connect to an already spawned agent on the UI thread. This can be used to coordinate state
between components or other agents. When no bridges are connected to this agent, the agent will
disappear.
* Job - Spawn a new agent on the UI thread for every new bridge. This is good for moving shared but
independent behavior that communicates with the browser out of components. \(TODO verify\) When the
task is done, the agent will disappear.
independent behavior that communicates with the browser out of components. \(TODO verify\) When the
task is done, the agent will disappear.
* Public - Same as Context, but runs on its own web worker.
* Private - Same as Job, but runs on its own web worker.
* Global \(WIP\)
@ -38,24 +38,19 @@ task is done, the agent will disappear.
### Bridges
A bridge allows bi-directional communication between an agent and a component. Bridges also allow
agents to communicate with one another.
A bridge allows bi-directional communication between an agent and a component. Bridges also allow agents to communicate with one another.
### Dispatchers
A dispatcher allows uni-directional communication between a component and an agent. A dispatcher
allows a component to send messages to an agent.
A dispatcher allows uni-directional communication between a component and an agent. A dispatcher allows a component to send messages to an agent.
## Overhead
Agents that live in their own separate web worker (Private and Public) incur serialization overhead
on the messages they send and receive. They use [bincode](https://github.com/servo/bincode) to
communicate with other threads, so the cost is substantially higher than just calling a function.
Unless the cost of computation will outweigh the cost of message passing, you should contain your
logic in the UI thread agents (Job or Context).
Agents that live in their own separate web worker \(Private and Public\) incur serialization overhead on the messages they send and receive. They use [bincode](https://github.com/servo/bincode) to communicate with other threads, so the cost is substantially higher than just calling a function. Unless the cost of computation will outweigh the cost of message passing, you should contain your logic in the UI thread agents \(Job or Context\).
## Further reading
* The [pub\_sub](https://github.com/yewstack/yew/tree/master/examples/pub_sub) example shows how
components can use agents to communicate with each other.
components can use agents to communicate with each other.

View File

@ -6,9 +6,7 @@ description: Components and their lifecycle hooks
## 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.
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
@ -20,9 +18,7 @@ of a component.
### 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.
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:
@ -46,9 +42,7 @@ impl Component for MyComponent {
### 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.
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 {
@ -69,10 +63,7 @@ For usage details, check out the `html!` guide:
### 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.
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;
@ -108,10 +99,7 @@ Note that this lifecycle method does not require an implementation and will do n
### 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.
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:
@ -142,9 +130,7 @@ impl Component for MyComponent {
### 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.
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:
@ -165,8 +151,7 @@ impl Component for MyComponent {
### 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.
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
@ -181,10 +166,7 @@ impl Component for MyComponent {
}
```
`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".
`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 {
@ -192,12 +174,5 @@ enum Msg {
}
```
`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.
`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.

View File

@ -4,37 +4,27 @@ description: ComponentLink and Callbacks
# Callbacks
The component "link" is the mechanism through which components are able to register callbacks and
update themselves.
The component "link" is the mechanism through which components are able to register callbacks and update themselves.
## ComponentLink API
### callback
Registers a callback that will send a message to the component's update mechanism when it is executed.
Under the hood, it will call `send_self` with the message that is returned by the provided closure.
A `Fn(IN) -> Vec<COMP::Message>` is provided and a `Callback<IN>` is returned.
Registers a callback that will send a message to the component's update mechanism when it is executed. Under the hood, it will call `send_self` with the message that is returned by the provided closure. A `Fn(IN) -> Vec<COMP::Message>` is provided and a `Callback<IN>` is returned.
### send\_message
Sends a message to the component immediately after the current loop finishes, causing another update
loop to initiate.
Sends a message to the component immediately after the current loop finishes, causing another update loop to initiate.
### send\_message\_batch
Registers a callback that sends a batch of many messages at once when it is executed. If any of the
messages cause the component to re-render, the component will re-render after all messages in the
batch have been processed. A `Fn(IN) -> COMP::Message` is provided and a `Callback<IN>` is returned.
Registers a callback that sends a batch of many messages at once when it is executed. If any of the messages cause the component to re-render, the component will re-render after all messages in the batch have been processed. A `Fn(IN) -> COMP::Message` is provided and a `Callback<IN>` is returned.
## Callbacks
_\(This might need its own short page.\)_
Callbacks are used to communicate with services, agents, and parent components within Yew. They are
just a `Fn` wrapped by an `Rc` to allow them to be cloned.
Callbacks are used to communicate with services, agents, and parent components within Yew. They are just a `Fn` wrapped by an `Rc` to allow them to be cloned.
They have an `emit` function that takes their `<IN>` type as an argument and converts that to a message expected by its destination. If a callback from a parent is provided in props to a child component, the child can call `emit` on the callback in its `update` lifecycle hook to send a message back to its parent. Closures or Functions provided as props inside the `html!` macro are automatically converted to Callbacks.
They have an `emit` function that takes their `<IN>` type as an argument and converts that to a
message expected by its destination. If a callback from a parent is provided in props to a child
component, the child can call `emit` on the callback in its `update` lifecycle hook to send a message
back to its parent. Closures or Functions provided as props inside the `html!` macro are
automatically converted to Callbacks.

View File

@ -11,45 +11,26 @@ Properties enable child and parent components to communicate with each other.
Don't try to implement `Properties` yourself, derive it by using `#[derive(Properties)]` instead.
{% hint style="info" %}
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using
`#[derive(Properties, Clone)` or manually implementing `Clone` for your type.
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)` or manually implementing `Clone` for your type.
{% endhint %}
### Required attributes
The fields within a struct that derives `Properties` are required by default. When a field is missing
and the component is created in the `html!` macro, a compiler error is returned. For fields with
optional properties, use the `#[prop_or_default]` attribute to use the default value for that type
when the prop is not specified. To specify a value, use the `#[prop_or(value)]` attribute where value
is the default value for the property or alternatively use `#[prop_or_else(function)]` where
`function` returns the default value. For example, to default a boolean value as `true`, use the
attribute `#[prop_or(true)]`. It is common for optional properties to use the `Option` enum which has the default value `None`.
The fields within a struct that derives `Properties` are required by default. When a field is missing and the component is created in the `html!` macro, a compiler error is returned. For fields with optional properties, use the `#[prop_or_default]` attribute to use the default value for that type when the prop is not specified. To specify a value, use the `#[prop_or(value)]` attribute where value is the default value for the property or alternatively use `#[prop_or_else(function)]` where `function` returns the default value. For example, to default a boolean value as `true`, use the attribute `#[prop_or(true)]`. It is common for optional properties to use the `Option` enum which has the default value `None`.
### PartialEq
It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq`
makes it much easier to avoid unnecessary rerendering \(this is explained in the
**Optimizations & Best Practices** section\).
It is likely to make sense to derive `PartialEq` on your props if you can do this. Using `PartialEq` makes it much easier to avoid unnecessary rerendering \(this is explained in the **Optimizations & Best Practices** section\).
## Memory/speed overhead of using Properties
In `Component::view`, you take a reference to the component's state, and use that to create `Html`.
Properties, however, are owned values. This means that in order to create them and pass them to child
components, we need to take ownership of the references provided in the `view` function. This is
done by implicitly cloning the references as they are passed to components in order to get owned
values.
In `Component::view`, you take a reference to the component's state, and use that to create `Html`. Properties, however, are owned values. This means that in order to create them and pass them to child components, we need to take ownership of the references provided in the `view` function. This is done by implicitly cloning the references as they are passed to components in order to get owned values.
This means that each component has its own distinct copy of the state passed down from its parent,
and that whenever you re-render a component, the props for all child components of the re-rendering
component will have to be cloned.
This means that each component has its own distinct copy of the state passed down from its parent, and that whenever you re-render a component, the props for all child components of the re-rendering component will have to be cloned.
The implication of this is if you would otherwise be passing _huge_ amounts of data down as props
\(Strings that are 10s of kilobytes in size\), you may want to consider turning your child component
into a function which returns `Html` that the parent calls, as this means that data does not have
to be cloned.
The implication of this is if you would otherwise be passing _huge_ amounts of data down as props \(Strings that are 10s of kilobytes in size\), you may want to consider turning your child component into a function which returns `Html` that the parent calls, as this means that data does not have to be cloned.
If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that
only a reference-counted pointer to the data is cloned, instead of the actual data itself.
If you won't need to modify the data passed down through props you can wrap it in an `Rc` so that only a reference-counted pointer to the data is cloned, instead of the actual data itself.
## Example
@ -91,3 +72,4 @@ pub struct LinkProps {
active: bool,
}
```

View File

@ -4,22 +4,19 @@ description: The procedural macro for generating HTML and SVG
# 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\).
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](lists.md)\)
[using fragments or iterators](lists.md)\)
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 `#![recursion_limit="1024"]`
in the crate root (i.e. either `lib.rs` or `main.rs`) to overcome the problem. See the
[official documentation](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) and
[this Stack Overflow question](https://stackoverflow.com/questions/27454761/what-is-a-crate-attribute-and-where-do-i-add-it)
for details.
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 `#![recursion_limit="1024"]` in the crate root \(i.e. either `lib.rs` or `main.rs`\) to overcome the problem. See the [official documentation](https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute) and [this Stack Overflow question](https://stackoverflow.com/questions/27454761/what-is-a-crate-attribute-and-where-do-i-add-it) for details.
{% endhint %}
{% page-ref page="lists.md" %}
@ -29,3 +26,4 @@ for details.
{% page-ref page="literals-and-expressions.md" %}
{% page-ref page="components.md" %}

View File

@ -63,14 +63,13 @@ impl Component for Container {
```
{% endcode %}
{% hint style="info" %} Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)]` or manually implementing `Clone` for your type. {% endhint %}
{% hint style="info" %}
Types for which you derive `Properties` must also implement `Clone`. This can be done by either using `#[derive(Properties, Clone)]` or manually implementing `Clone` for your type.
{% endhint %}
## Nested Children with Props
Nested component properties can be accessed and mutated if the containing component types its children.
In the following example, the `List` component can wrap `ListItem` components. For a real world example
of this pattern, check out the `yew-router` source code. For a more advanced example, check out the
`nested-list` example in the main yew repository.
Nested component properties can be accessed and mutated if the containing component types its children. In the following example, the `List` component can wrap `ListItem` components. For a real world example of this pattern, check out the `yew-router` source code. For a more advanced example, check out the `nested-list` example in the main yew repository.
{% code title="parent.rs" %}
```rust
@ -109,3 +108,4 @@ impl Component for List {
}
```
{% endcode %}

View File

@ -43,8 +43,7 @@ html! {
{% endtabs %}
{% hint style="info" %}
For convenience, elements which _usually_ require a closing tag are **allowed** to self-close. For
example, writing `html! { <div class="placeholder" /> }` is valid.
For convenience, elements which _usually_ require a closing tag are **allowed** to self-close. For example, writing `html! { <div class="placeholder" /> }` is valid.
{% endhint %}
## Children
@ -152,8 +151,7 @@ html! {
## Listeners
Listener attributes need to be passed a `Callback` which is a wrapper around a closure. How you
create your callback depends on how you wish your app to react to a listener event:
Listener attributes need to be passed a `Callback` which is a wrapper around a closure. How you create your callback depends on how you wish your app to react to a listener event:
{% tabs %}
{% tab title="Component Handler" %}

View File

@ -2,8 +2,7 @@
## Fragments
The `html!` macro always requires a single root node. In order to get around this restriction, it's
valid to wrap content in empty tags:
The `html!` macro always requires a single root node. In order to get around this restriction, it's valid to wrap content in empty tags:
{% tabs %}
{% tab title="Valid" %}

View File

@ -2,11 +2,9 @@
## Literals
If expressions resolve to types that implement `Display`, they will be converted to strings and
inserted into the DOM as a [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) node.
If expressions resolve to types that implement `Display`, they will be converted to strings and inserted into the DOM as a [Text](https://developer.mozilla.org/en-US/docs/Web/API/Text) node.
All display text must be enclosed by `{}` blocks because text is handled like an expression. This is
the largest deviation from normal HTML syntax that Yew makes.
All display text must be enclosed by `{}` blocks because text is handled like an expression. This is the largest deviation from normal HTML syntax that Yew makes.
```rust
let text = "lorem ipsum";
@ -39,8 +37,7 @@ html! {
}
```
It often makes sense to extract these expressions into functions or closures to optimize for
readability:
It often makes sense to extract these expressions into functions or closures to optimize for readability:
```rust
let show_link = true;

View File

@ -6,9 +6,7 @@ description: Yew's official router
[https://crates.io/crates/yew-router](https://crates.io/crates/yew-router)
Routers in Single Page Applications \(SPA\) handle displaying different pages depending on what the URL is. Instead of
the default behavior of requesting a different remote resource when a link is clicked, the router instead sets the URL
locally to point to a valid route in your application. The router then detects this change and then decides what to render.
Routers in Single Page Applications \(SPA\) handle displaying different pages depending on what the URL is. Instead of the default behavior of requesting a different remote resource when a link is clicked, the router instead sets the URL locally to point to a valid route in your application. The router then detects this change and then decides what to render.
## Core Elements
@ -22,8 +20,7 @@ Communicates with the browser to get and set Routes.
### RouteAgent
Owns a RouteService and is used to coordinate updates when the route changes, either from within the application logic
or from an event fired from the browser.
Owns a RouteService and is used to coordinate updates when the route changes, either from within the application logic or from an event fired from the browser.
### Switch
@ -31,16 +28,13 @@ The `Switch` trait is used to convert a `Route` to and from the implementer of t
### Router
The Router component communicates with `RouteAgent` and will automatically resolve Routes it gets from the agent into
switches, which it will expose via a `render` prop that allows specifying how the resulting switch gets converted to `Html`.
The Router component communicates with `RouteAgent` and will automatically resolve Routes it gets from the agent into switches, which it will expose via a `render` prop that allows specifying how the resulting switch gets converted to `Html`.
## How to use the Router
First, you want to create a type that represents all the states of your application. Do note that while this typically
is an enum, structs are supported as well, and that you can nest other items that implement `Switch` inside.
First, you want to create a type that represents all the states of your application. Do note that while this typically is an enum, structs are supported as well, and that you can nest other items that implement `Switch` inside.
Then you should derive `Switch` for your type. For enums, every variant must be annotated with `#[to = "/some/route"]`,
or if you use a struct instead, that must appear outside the struct declaration.
Then you should derive `Switch` for your type. For enums, every variant must be annotated with `#[to = "/some/route"]`, or if you use a struct instead, that must appear outside the struct declaration.
```rust
#[derive(Switch)]
@ -60,10 +54,7 @@ enum AppRoute {
}
```
Do note that the implementation generated by the derive macro for `Switch` will try to match each variant in order from
first to last, so if any route could possibly match two of your specified `to` annotations, then the first one will
match, and the second will never be tried. For example, if you defined the following `Switch`, the only route that would
be matched would be `AppRoute::Home`.
Do note that the implementation generated by the derive macro for `Switch` will try to match each variant in order from first to last, so if any route could possibly match two of your specified `to` annotations, then the first one will match, and the second will never be tried. For example, if you defined the following `Switch`, the only route that would be matched would be `AppRoute::Home`.
```rust
#[derive(Switch)]
@ -83,16 +74,9 @@ enum AppRoute {
}
```
You can also capture sections using variations of `{}` within your `#[to = ""]` annotation. `{}`
means capture text until the next separator \(either "/", "?", "&", or "\#" depending on the context\).
`{*}` means capture text until the following characters match, or if no characters are present, it
will match anything. `{<number>}` means capture text until the specified number of separators are
encountered \(example: `{2}` will capture until two separators are encountered\).
You can also capture sections using variations of `{}` within your `#[to = ""]` annotation. `{}` means capture text until the next separator \(either "/", "?", "&", or "\#" depending on the context\). `{*}` means capture text until the following characters match, or if no characters are present, it will match anything. `{<number>}` means capture text until the specified number of separators are encountered \(example: `{2}` will capture until two separators are encountered\).
For structs and enums with named fields, you must specify the field's name within the capture group
like so: `{user_name}` or `{*:age}`.
For structs and enums with named fields, you must specify the field's name within the capture group like so: `{user_name}` or `{*:age}`.
The Switch trait works with capture groups that are more structured than just Strings. You can
specify any type that implements `Switch`. So you can specify that the capture group is a `usize`,
and if the captured section of the URL can't be converted to it, then the variant won't match.
The Switch trait works with capture groups that are more structured than just Strings. You can specify any type that implements `Switch`. So you can specify that the capture group is a `usize`, and if the captured section of the URL can't be converted to it, then the variant won't match.

View File

@ -1,6 +1,6 @@
# Build a Sample App
First create a new Rust library (**important:** create a *library*, not a *binary* by passing the `--lib` flag):
First create a new Rust library \(**important:** create a _library_, not a _binary_ by passing the `--lib` flag\):
```bash
cargo new --lib yew-app && cd yew-app
@ -20,7 +20,7 @@ edition = "2018"
crate-type = ["cdylib", "rlib"]
[dependencies]
yew = "0.16"
yew = "0.17"
wasm-bindgen = "0.2"
```
{% endcode %}
@ -82,10 +82,7 @@ pub fn run_app() {
```
{% endcode %}
This template sets up your root `Component`, called `Model` which shows a button that updates itself when you click it.
Take special note of `App::<Model>::new().mount_to_body()` inside `main()` which starts your app and mounts it to the
page's `<body>` tag. If you would like to start your application with any dynamic properties, you can instead use
`App::<Model>::new().mount_to_body_with_props(..)`.
This template sets up your root `Component`, called `Model` which shows a button that updates itself when you click it. Take special note of `App::<Model>::new().mount_to_body()` inside `main()` which starts your app and mounts it to the page's `<body>` tag. If you would like to start your application with any dynamic properties, you can instead use `App::<Model>::new().mount_to_body_with_props(..)`.
Finally, add an `index.html` file into a new folder named `static` in your app.
@ -112,16 +109,13 @@ mkdir static
## Run your App!
Using [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) is the preferred way to get up and
running. If you haven't already, install `wasm-pack` with `cargo install wasm-pack` and then build
and start a development server by running:
Using [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) is the preferred way to get up and running. If you haven't already, install `wasm-pack` with `cargo install wasm-pack` and then build and start a development server by running:
```bash
wasm-pack build --target web --out-name wasm --out-dir ./static
```
`wasm-pack` generates a bundle in the `./static` directory with your app's compiled WebAssembly along
with a JavaScript wrapper which will load your application's WebAssembly binary and run it.
`wasm-pack` generates a bundle in the `./static` directory with your app's compiled WebAssembly along with a JavaScript wrapper which will load your application's WebAssembly binary and run it.
Then, use your favorite web server to server the files under `./static`. For example:

View File

@ -1,18 +1,16 @@
# Choosing between web-sys and stdweb
# Choose web-sys or stdweb
## Introduction
Yew apps can be built with either [`web-sys`](https://docs.rs/web-sys) or
[`stdweb`](https://docs.rs/stdweb). These two crates provide the bindings between Rust and Web APIs.
You'll need to choose one or the other when adding `yew` to your cargo dependencies:
Yew apps can be built with either [`web-sys`](https://docs.rs/web-sys) or [`stdweb`](https://docs.rs/stdweb). These two crates provide the bindings between Rust and Web APIs. You'll need to choose one or the other when adding `yew` to your cargo dependencies:
{% code title="Cargo.toml" %}
```rust
# Choose `web-sys`
yew = "0.16"
yew = "0.17"
# Choose `stdweb`
yew = { version = "0.16", package = "yew-stdweb" }
yew = { version = "0.17", package = "yew-stdweb" }
```
{% endcode %}
@ -39,44 +37,54 @@ let window = Window::try_from(window_val).expect("conversion to window failed");
window.alert("hello from wasm!");
```
The APIs for the two crates differ slightly but they serve roughly the same purpose with similar
functionality.
The APIs for the two crates differ slightly but they serve roughly the same purpose with similar functionality.
## Choosing One
There are a few different angles to consider when choosing between using `web-sys` and `stdweb` for
your app. Note that it's possible to use both in one app, but to minimize the binary size of your
compiled crate it's best to use only one of the two.
| | `web-sys` | `stdweb` |
| :--- | :--- | :--- |
| Project Status | Actively maintained by the [Rust / Wasm Working Group](https://rustwasm.github.io/) | No Github activity for over 4 months |
| :--- | :--- | :--- |
| Web API Coverage | Rust APIs are auto-generated from the Web IDL spec and so should have 100% coverage. | Browser APIs are added as needed by the community |
| :--- | :--- | :--- |
| Rust API Design | Takes conservative approach by returning `Result` for most API calls | Often avoids `Result` in favor of panics. For instance, `stdweb::web::window()` will panic when called in a worker. |
| :--- | :--- | :--- |
There are a few different angles to consider when choosing between using `web-sys` and `stdweb` for your app. Note that it's possible to use both in one app, but to minimize the binary size of your compiled crate it's best to use only one of the two.
<table>
<thead>
<tr>
<th style="text-align:left">Supported Build Tools</th>
<th style="text-align:left">
<th style="text-align:left"></th>
<th style="text-align:left"><code>web-sys</code>
</th>
<th style="text-align:left"><code>stdweb</code>
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Project Status</td>
<td style="text-align:left">Actively maintained by the <a href="https://rustwasm.github.io/">Rust / Wasm Working Group</a>
</td>
<td style="text-align:left">No Github activity for over 8 months</td>
</tr>
<tr>
<td style="text-align:left">Web API Coverage</td>
<td style="text-align:left">Rust APIs are auto-generated from the Web IDL spec</td>
<td style="text-align:left">Browser APIs are added as needed by the community</td>
</tr>
<tr>
<td style="text-align:left">Rust API Design</td>
<td style="text-align:left">Takes conservative approach by returning <code>Result</code> for most API
calls</td>
<td style="text-align:left">Often avoids <code>Result</code> in favor of panics. For instance, <code>stdweb::web::window()</code> will
panic when called in a worker</td>
</tr>
<tr>
<td style="text-align:left">Supported Build Tools</td>
<td style="text-align:left">
<p></p>
<ul>
<li><code>wasm-bindgen</code>
</li>
<li><code>wasm-pack</code>
</li>
</ul>
</th>
<th style="text-align:left">
</td>
<td style="text-align:left">
<p></p>
<ul>
<li><code>cargo-web</code>
</li>
@ -85,21 +93,17 @@ compiled crate it's best to use only one of the two.
<li><code>wasm-pack</code>
</li>
</ul>
</th>
</td>
</tr>
</thead>
<tbody></tbody>
</table><table>
<thead>
<tr>
<th style="text-align:left">Supported Targets</th>
<th style="text-align:left">
<td style="text-align:left">Supported Targets</td>
<td style="text-align:left">
<ul>
<li><code>wasm32-unknown-unknown</code>
</li>
</ul>
</th>
<th style="text-align:left">
</td>
<td style="text-align:left">
<ul>
<li><code>wasm32-unknown-unknown</code>
</li>
@ -108,8 +112,8 @@ compiled crate it's best to use only one of the two.
<li><code>asmjs-unknown-emscripten</code>
</li>
</ul>
</th>
</td>
</tr>
</thead>
<tbody></tbody>
</tbody>
</table>

View File

@ -1,12 +1,10 @@
# Learn through examples
The Yew repository is chock-full of [examples](https://github.com/yewstack/yew/tree/v0.16.0/examples)
\(in various states of maintenance\). We recommend perusing them to get a feel for how to use
different framework features. We also welcome Pull Requests and issues for when they inevitably get
neglected and need some ♥️
The Yew repository is chock-full of [examples](https://github.com/yewstack/yew/tree/v0.17/examples) \(in various states of maintenance\). We recommend perusing them to get a feel for how to use different framework features. We also welcome Pull Requests and issues for when they inevitably get neglected and need some ♥️
* [**Todo App** ](https://github.com/yewstack/yew/tree/v0.16.0/examples/todomvc)
* [**Custom Components**](https://github.com/yewstack/yew/tree/v0.16.0/examples/custom_components)
* [**Multi-threading \(Agents\)**](https://github.com/yewstack/yew/tree/v0.16.0/examples/multi_thread)
* [**Timer Service**](https://github.com/yewstack/yew/tree/v0.16.0/examples/timer)
* [**Todo App** ](https://github.com/yewstack/yew/tree/v0.17/examples/todomvc)
* [**Custom Components**](https://github.com/yewstack/yew/tree/v0.17/examples/custom_components)
* [**Multi-threading \(Agents\)**](https://github.com/yewstack/yew/tree/v0.17/examples/multi_thread)
* [**Timer Service**](https://github.com/yewstack/yew/tree/v0.17/examples/timer)
* [**Nested Components**](https://github.com/yewstack/yew/tree/v0.16.0/examples/nested_list)

View File

@ -6,37 +6,27 @@ description: Set yourself up for success
## Rust
First, you'll need Rust. To install Rust and the `cargo` build tool, follow the
[official instructions](https://www.rust-lang.org/tools/install).
First, you'll need Rust. To install Rust and the `cargo` build tool, follow the [official instructions](https://www.rust-lang.org/tools/install).
## **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.
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`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack.
A CLI tool developed by the Rust / Wasm Working Group for packaging up WebAssembly. Best used together with the [`wasm-pack-plugin`](https://github.com/wasm-tool/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-bindgen`directly 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**](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-bindgen`directly 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**](https://rustwasm.github.io/docs/wasm-bindgen/).
{% 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.
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" %}
@ -142,3 +132,4 @@ been migrated to support `wasm-pack` yet.
</tr>
</tbody>
</table>

View File

@ -1,8 +1,6 @@
# Using cargo-web
Cargo web is a cargo subcommand for building client web apps. It makes building and deploying web
applications incredibly easy. It is also the only toolchain that supports Emscripten targets. Read
more [here](https://github.com/koute/cargo-web).
Cargo web is a cargo subcommand for building client web apps. It makes building and deploying web applications incredibly easy. It is also the only toolchain that supports Emscripten targets. Read more [here](https://github.com/koute/cargo-web).
**Install**
@ -10,19 +8,19 @@ more [here](https://github.com/koute/cargo-web).
cargo install cargo-web
```
### Build
## Build
```bash
cargo web build
```
### Run
## Run
```bash
cargo web start
```
### Supported Targets
## Supported Targets
* `wasm32-unknown-unknown`
* `wasm32-unknown-emscripten`

View File

@ -1,31 +1,26 @@
# Using wasm-pack
This tool was created by the Rust / Wasm Working Group and is the most actively developed tool for
building WebAssembly applications. It supports packaging code into `npm` modules and has an
accompanying [Webpack plugin](https://github.com/wasm-tool/wasm-pack-plugin) for easy integration
with an existing JavaScript application. More information is given in
[the `wasm-pack` documentation](https://rustwasm.github.io/docs/wasm-pack/introduction.html).
This tool was created by the Rust / Wasm Working Group and is the most actively developed tool for building WebAssembly applications. It supports packaging code into `npm` modules and has an accompanying [Webpack plugin](https://github.com/wasm-tool/wasm-pack-plugin) for easy integration with an existing JavaScript application. More information is given in [the `wasm-pack` documentation](https://rustwasm.github.io/docs/wasm-pack/introduction.html).
{% hint style="info" %}
Note that the crate-type in your `Cargo.toml` will need to be `cdylib` when using `wasm-pack`
{% endhint %}
### Install
## Install
```bash
cargo install wasm-pack
```
### Build
## Build
This command will produce a bundle in the `./pkg` directory with your app's compiled WebAssembly
along with a JavaScript wrapper which can be used to start your application.
This command will produce a bundle in the `./pkg` directory with your app's compiled WebAssembly along with a JavaScript wrapper which can be used to start your application.
```bash
wasm-pack build --target web
```
### Bundle
## Bundle
For more information on Rollup visit this [guide](https://rollupjs.org/guide/en/#quick-start)
@ -33,16 +28,15 @@ For more information on Rollup visit this [guide](https://rollupjs.org/guide/en/
rollup ./main.js --format iife --file ./pkg/bundle.js
```
### Serve
## Serve
Feel free to use your preferred server. Here we use a simple python server to serve to
[http://\[::1\]:8000](http://[::1]:8000).
Feel free to use your preferred server. Here we use a simple python server to serve to
```bash
python -m http.server 8000
```
### Supported Targets
## Supported Targets
* `wasm32-unknown-unknown`

View File

@ -3,12 +3,14 @@
## `wasm-pack`
* [Minimal Template](https://github.com/yewstack/yew-wasm-pack-minimal) - Uses `wasm-pack` and
`rollup` to build your application, and your own server to serve it. No bells or whistles here.
* [Webpack Template](https://github.com/yewstack/yew-wasm-pack-template) - Uses `wasm-pack` and the
[`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack to streamline development.
The important distinction between these templates and using `cargo-web` is that this approach uses a
`lib`, not a `bin` crate, and the entry-point to your program is annotated with a `#[wasm_bindgen]` annotation.
`rollup` to build your application, and your own server to serve it. No bells or whistles here.
* [Webpack Template](https://github.com/yewstack/yew-wasm-pack-template) - Uses `wasm-pack` and the
[`wasm-pack-plugin`](https://github.com/wasm-tool/wasm-pack-plugin) for Webpack to streamline development.
The important distinction between these templates and using `cargo-web` is that this approach uses a `lib`, not a `bin` crate, and the entry-point to your program is annotated with a `#[wasm_bindgen]` annotation.
Your `Cargo.toml` also should specify that your crate's type is a "cdylib".
@ -25,9 +27,9 @@ crate-type = ["cdylib"]
[dependencies]
# for web_sys
yew = "0.16"
yew = "0.17"
# or for stdweb
# yew = { version = "0.16", package = "yew-stdweb" }
# yew = { version = "0.17", package = "yew-stdweb" }
wasm-bindgen = "0.2"
```
{% endcode %}
@ -35,4 +37,6 @@ wasm-bindgen = "0.2"
## Other templates
* [Parcel Template](https://github.com/spielrs/yew-parcel-template) - Created by a community member
and uses [Parcel](https://parceljs.org/)
and uses [Parcel](https://parceljs.org/)

View File

@ -2,5 +2,5 @@
&lt;TODO&gt;
A proposal for integrated CSS support can be found here:
[https://github.com/yewstack/yew/issues/533](https://github.com/yewstack/yew/issues/533)
A proposal for integrated CSS support can be found here: [https://github.com/yewstack/yew/issues/533](https://github.com/yewstack/yew/issues/533)

View File

@ -2,13 +2,11 @@
## Panics
Please use the [`console_error_panic`](https://github.com/rustwasm/console_error_panic_hook) crate for nicer stacktraces
with Rust symbols. Note, that it is not compatible with apps built with `cargo-web`.
Please use the [`console_error_panic`](https://github.com/rustwasm/console_error_panic_hook) crate for nicer stacktraces with Rust symbols. Note, that it is not compatible with apps built with `cargo-web`.
## Console Logging
In general, Wasm web apps are able to interact with Browser APIs, and the `console.log` api is no exception. There are
a few options available:
In general, Wasm web apps are able to interact with Browser APIs, and the `console.log` api is no exception. There are a few options available:
### [`wasm-logger`](https://crates.io/crates/wasm-logger)
@ -35,8 +33,7 @@ ConsoleService::new()::info(format!("Update: {:?}", msg));
## Source Maps
There is currently no first-class support for source maps for Rust / Wasm web apps. This, of course, is subject to
change. If this is no longer true or if progress is made, please suggest a change!
There is currently no first-class support for source maps for Rust / Wasm web apps. This, of course, is subject to change. If this is no longer true or if progress is made, please suggest a change!
### Latest Info
@ -51,3 +48,4 @@ change. If this is no longer true or if progress is made, please suggest a chang
\[2019\] [Rust Wasm roadmap](https://rustwasm.github.io/rfcs/007-2019-roadmap.html#debugging)
> Debugging is tricky because much of the story is out of this working group's hands, and depends on both the WebAssembly standardization bodies and the folks implementing browser developer tools instead.

View File

@ -10,11 +10,16 @@ Yewtil is a collection of common utilities that help you write Yew programs. It
* NeqAssign - As discussed earlier, is the best way to assign props to ensure minimal re-rendering.
* PureComponents - Components that don't update any of their state. Using NeqAssign under the hood, they act as memoized
functions that are called from inside the `html!` macro like normal components are.
functions that are called from inside the `html!` macro like normal components are.
* Lrc - linked list reference counted smart pointer functions like `Rc` does, but allows for novel data update patterns.
* Mrc/Irc - Mutable/Immutable reference counted smart pointers that function like `Rc` but are more ergonomic to use
within Yew, due to implementing `DerefMut` and `BorrowMut`for `Mrc`. This allows `Mrc` to be used with `NeqAssign`.
`Irc` acts as an immutable view into the data, which makes this ideal for holding data used in display-only tasks.
within Yew, due to implementing `DerefMut` and `BorrowMut`for `Mrc`. This allows `Mrc` to be used with `NeqAssign`.
`Irc` acts as an immutable view into the data, which makes this ideal for holding data used in display-only tasks.
* History - A history tracking wrapper that uses a `VecDeque` to hold on to previous values that it has represented.
* Futures - Support for running futures that send messages to component update loops.
* Fetch - Abstractions for handling fetch requests made using `web_sys` and the aforementioned futures feature.

View File

@ -4,44 +4,42 @@ description: The planned feature roadmap for the Yew framework
# Roadmap
### Prioritization
## Prioritization
The prioritization of upcoming features and focuses of the framework are determined by the community. In Spring 2020, a
developer survey was sent out to collect feedback on the direction of the project. You can find the summary in the
[Yew Wiki](https://github.com/yewstack/yew/wiki/Dev-Survey-%5BSpring-2020%5D).
The prioritization of upcoming features and focuses of the framework are determined by the community. In Spring 2020, a developer survey was sent out to collect feedback on the direction of the project. You can find the summary in the [Yew Wiki](https://github.com/yewstack/yew/wiki/Dev-Survey-%5BSpring-2020%5D).
{% hint style="info" %}
Status of all major initiatives can be tracked on the Yew Github [Project board](https://github.com/yewstack/yew/projects)
{% endhint %}
### Focuses
## Focuses
1. Top Requested Features
2. Production Readiness
3. Documentation
4. Pain Points
#### Top Requested Features
### Top Requested Features
1. [Functional Components](https://github.com/yewstack/yew/projects/3)
2. [Component Library](https://github.com/yewstack/yew/projects/4)
3. Better state management
4. [Server side rendering](https://github.com/yewstack/yew/projects/5)
#### Production Readiness
### Production Readiness
* Improve Yew test coverage
* Reduce binary size
* [Benchmark performance](https://github.com/yewstack/yew/issues/5)
#### Documentation
### Documentation
* Create tutorial
* Simplify project setup
#### Pain Points
### Pain Points
* [Component boilerplate](https://github.com/yewstack/yew/issues/830)
* Fetch API
* Agents
* [Agents](https://github.com/yewstack/yew/projects/6)

View File

@ -8,9 +8,5 @@ description: Testing your app
## wasm\_bindgen\_test
The Rust Wasm working group maintains a crate called
[`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) which allows you to run
tests in a browser in similar fashion to how the built-in `#[test]` procedural macro works. More information is given
in the [Rust WASM working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html)
for this module.
The Rust Wasm working group maintains a crate called [`wasm_bindgen_test`](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) which allows you to run tests in a browser in similar fashion to how the built-in `#[test]` procedural macro works. More information is given in the [Rust WASM working group's documentation](https://rustwasm.github.io/docs/wasm-bindgen/wasm-bindgen-test/index.html) for this module.