---
title: 'Optimizations & Best Practices'
sidebar_label: Optimizations
description: 'Make your app faster'
---

## Using smart pointers effectively

**Note: if you're unsure about some of the terms used in this section, the Rust Book has a useful
[chapter about smart pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html).**

To avoid cloning large amounts of data to create props when re-rendering, we can use
smart pointers to only clone a reference to the data instead of the data itself. If you pass
references to the relevant data in your props and child components instead of the actual data you
can avoid cloning any data until you need to modify it in the child component, where you can
use `Rc::make_mut` to clone and obtain a mutable reference to the data you want to alter.

This brings further benefits in `Component::changed` when working out whether prop changes require
the component to re-render. This is because instead of comparing the value of the data the
underlying pointer addresses (i.e. the position in a machine's memory where the data is stored) can
instead be compared; if two pointers point to the same data then the value of the data they point to
must be the same. Note that the inverse might not be true! Even if two pointer addresses differ the
underlying data might still be the same - in this case you should compare the underlying data.

To do this comparison you'll need to use `Rc::ptr_eq` instead of just using `PartialEq` (which is
automatically used when comparing data using the equality operator `==`). The Rust documentation
has [more details about `Rc::ptr_eq`](https://doc.rust-lang.org/stable/std/rc/struct.Rc.html#method.ptr_eq).

This optimization is most useful for data types that don't implement `Copy`. If you can copy your
data cheaply, then it isn't worth putting it behind a smart pointer. For structures that
can be data-heavy like `Vec`s, `HashMap`s, and `String`s using smart pointers is likely to bring
performance improvements.

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 pure components.

However, it must be noted that unless you need to clone the data yourself in the child component,
this optimization is not only useless, but it also adds the unnecessary cost of reference counting. Props
in Yew are already reference counted and no data clones occur internally.

## View functions

For code readability reasons, it often makes sense to migrate sections of `html!` to their own
functions. Not only does this make your code more readable because it reduces the amount of
indentation present, it also encourages good design patterns – particularly around building
composable applications because these functions can be called in multiple places which reduces the
amount of code that has to be written.

## Pure 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 (this means that once a function is called its value is "saved"
so that if it's called with the same arguments more than once it doesn't have to recompute its value
and can just return the saved value from the first function call) - preventing re-renders for
identical props. Yew compares the props internally and so the UI is only re-rendered if the props change.

## Reducing compile time using workspaces

Arguably, the largest drawback to using Yew is the long time it takes to compile Yew apps. The time
taken to compile a project seems to be related to the quantity of code passed to the `html!` macro.
This tends to not be much of an issue for smaller projects, but for larger applications, it makes
sense to split code across multiple crates to minimize the amount of work the compiler has to do for
each change made to the application.

One possible approach is to make your main crate handle routing/page selection, 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`. Code that is shared between the crates containing different parts of
the application could be stored in a separate crate which the project depends on.
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 simplified
implementation of the main page and additionally render the component you are working on.

## Reducing binary sizes

-   optimize Rust code
-   `cargo.toml` \( defining release profile \)
-   optimize wasm code using `wasm-opt`

**Note: more information about reducing binary sizes can be found in the
[Rust Wasm Book](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size).**

### Cargo.toml

It is possible to configure release builds to be smaller using the available settings in the
`[profile.release]` section of your `Cargo.toml`.

```toml, title=Cargo.toml
[profile.release]
# less code to include into binary
panic = 'abort'
# optimization over all codebase ( better optimization, slower build )
codegen-units = 1
# optimization for size ( more aggressive )
opt-level = 'z'
# optimization for size
# opt-level = 's'
# link time optimization using using whole-program analysis
lto = true
```

### Nightly Cargo configuration

You can also gain additional benefits from experimental nightly features of rust and
cargo. To use the nightly toolchain with `trunk`, set the `RUSTUP_TOOLCHAIN="nightly"` environment
variable. Then, you can configure unstable rustc features in your `.cargo/config.toml`.
Refer to the doc of [unstable features], specifically the section about [`build-std`] and
[`build-std-features`], to understand the configuration.

```toml, title=".cargo/config.toml"
[unstable]
# Requires the rust-src component. `rustup +nightly component add rust-src`
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort"]
```

[unstable features]: https://doc.rust-lang.org/cargo/reference/unstable.html
[`build-std`]: https://doc.rust-lang.org/cargo/reference/unstable.html#build-std
[`build-std-features`]: https://doc.rust-lang.org/cargo/reference/unstable.html#build-std-features

:::caution
The nightly rust compiler can contain bugs, such as [this one](https://github.com/yewstack/yew/issues/2696),
that require occasional attention and tweaking. Use these experimental options with care.
:::

### wasm-opt

Further, it is possible to optimize the size of `wasm` code.

The Rust Wasm Book has 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.

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

| used tool                   | size  |
| :-------------------------- | :---- |
| wasm-bindgen                | 158KB |
| wasm-bindgen + wasm-opt -Os | 116KB |
| wasm-pack                   | 99 KB |

## Further reading

-   [The Rust Book's chapter on smart pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html)
-   [Information from the Rust Wasm Book about reducing binary sizes](https://rustwasm.github.io/book/reference/code-size.html#optimizing-builds-for-code-size)
-   [Documentation about Rust profiles](https://doc.rust-lang.org/cargo/reference/profiles.html)
-   [binaryen project](https://github.com/WebAssembly/binaryen)
