Skip to main content
Version: 0.21

優化與最佳實例

neq_assign

當元件從父元件接收到屬性時, change 的方法就會被呼叫。除了讓你更新元件的狀態,也讓你回傳,決定元件是否要在屬性改變時,重新渲染自己的布林值 ShouldRender

重新渲染是很浪費效能的,儘可能避免這麼做。一般來說,只有在屬性真的改變時,才重新渲染。下面的程式碼是體現這個原則的例子,當屬性改變時,才回傳 true

use yew::ShouldRender;

#[derive(PartialEq)]
struct ExampleProps;

struct Example {
props: ExampleProps,
};

impl Example {
fn change(&mut self, props: ExampleProps) -> ShouldRender {
if self.props != props {
self.props = props;
true
} else {
false
}
}
}

但我們可以走的更遠!這六行的模板,使用一個 trait 和一個 實作了 PartialEq 的 blanket implementation ,可以被縮短至一行。請參考這裡yewtil 的 crate 裡的 NeqAssign trait。

RC

為了避免重新渲染時,複製大量的資料來建立屬性,我們可以使用智慧指針來讓程式只複製指針。如果你使用 Rc<_> 來封裝你的屬性,而不是未封裝的值,你可以使用 Rc::make_mut,去複製與存取你想要改變的資料的可變參考,這做到了延遲複製,直到你需要更動子元件的資料。透過避免複製直到有值改變,子元件可以在 Component::change 拒絕與他狀態中的屬性相同值的屬性,而且這樣不會有任何效能成本。另外,這個方式,資料必須在與子元件比較與被拒絕之前,被複製進父元件的屬性中。

這個優化最那些無法 Copy 的資料型別最有用。如果你可以輕易複製你的資料,那把資料放進智慧指針裡面似乎就沒有這麼值得。對於那些包含很多像是 VecHashMapString 的結構,這個優化對他們會更值得。

如果子元件幾乎不會更新值,那這個優化效果會很好,甚至如果父元件也很少更新,那效果會更好。上面的情況,使在純元件中使用 Rc<_>s 是一個封裝屬性值很好的選擇。

View 方法

出於程式碼的可讀性,通常會寫方法包裝複雜的 html!,這樣你可以避免巢狀的 HTML 造成過多的向右縮排。

純元件/函數式元件

純元件 是一種不會改變自己狀態的元件,他們只單純顯示內容或是向普通可變的元件傳送訊息。他們和 view 方法不同的地方在於們可以在 html! 巨集中使用,語法會像(<SomePureComponent />),而不是表達式語法({some_view_function()}),而且根據他們的實作方式,他們可以被 memoized,這樣可以套用前面所述的 neq_assign 的邏輯避免重新渲染。

Yew 本身不支援純元件或是函數式元件,但是你可以透過 external crates 使用。

函數式元件還不存在,但是理論上純元件可以透過巨集與宣告方法產生。

Keyed DOM nodes when they arrive

使用 Cargo Workspaces 加速編譯

Yew 最大的缺點就是花太多時間在編譯上了。編譯時間似乎和 html! 巨集中的程式碼質量相同。 對於小專案來說,這應該不是什麼大問題,但是對於有很多頁面的大型網頁應用程式來說,就必須要將程式碼封裝成很多 crates 以減少編譯所花的時間。

你應該將路由與頁面區塊封裝成一個 main crate,然後將共用的程式碼與元件封裝成另一個 crate,將每個頁面會用到的不同的元件,各自封裝到不同的 crate 中,或是只產生 Html 的大方法中。最好的狀況,你只需要重新編譯你 main crate 與修改的頁面的 crate 的程式碼;而最壞的情況,你編輯了共用的 crate,你就必須重新編譯所有依賴這個共用 crate 的程式碼。

如果你的 main crate 太過龐大,或是你希望快速迭代深層巢狀的頁面(一個頁面渲染另一個頁面的頂層),你可以使用範例的 crate ,在一個簡單的主頁面上編輯你未完成的元件。

編譯大小的優化

  • 優化 Rust 的程式碼
  • cargo.toml (定義釋出的設定檔)
  • 使用 wasm-opt 優化 wasm 程式碼

更多關於程式碼大小的資訊,請參考: rustwasm book

Cargo.toml

你可以設定你的發行版本更小的檔案大小,透過設定 Cargo.toml[profile.release]

Rust profiles documentation

[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 aggresive )
opt-level = 'z'
# optimization for size
# opt-level = 's'
# link time optimization using using whole-program analysis
lto = true

wasm-opt

更多優化 wasm 程式碼大小的方法。

wasm-opt 資訊: binaryen project

Rust Wasm 中有一個關於減少 Wasm 二進位檔大小的章節:Shrinking .wasm size

  • 使用wasm-pack 預設在發行版本編譯時優化 wasm 程式碼
  • 直接在 wasm 檔案上使用 wasm-opt
wasm-opt wasm_bg.wasm -Os -o wasm_bg_opt.wasm

編譯 yew/examples/ 中 最小的例子

注意: wasm-pack 包含對 Rust 與 wasm 程式碼的優化。而wasm-bindgen 只是一個單純的例子,沒有對 Rust 做任何優化。

used toolsize
wasm-bindgen158KB
wasm-binggen + wasm-opt -Os116KB
wasm-pack99KB