优化和最佳实践
有效使用智能指针
注意:如果您不确定本节中使用的一些术语,Rust Book 中有一个有用的有关智能指针的章节。
为了避免在重新渲染时克隆大量数据以创建属性,我们可以使用智能指针仅克隆对数据的引用,而不是数据本身。如果您在属性和子组件中传递对相关数据的引用,而不是实际数据,则可以避免克隆任何数据,直到您需要在子组件中修改它,您可以在其中使用 Rc::make_mut
来克隆并获取您要修改的数据的可变引用。
当确定属性更改是否需要组件重新渲染时,这会给 Component::changed
带来越多的好处。这是因为,可以比较底层指针地址(即存储数据的机器内存中的位置),而不是比较数据的数值;如果两个指针指向相同的数据,那么它们指向的数据的数值必定相同。注意,反过来可能不是真的!即使两个指针地址不同,底层数据仍然可能相同 - 在这种情况下,您应该比较底层数据。
要进行此比较,您需要使用 Rc::ptr_eq
,而不是仅仅使用 PartialEq
(在使用相等运算符 ==
比较数据时会自动使用)。Rust 文档有 关于 Rc::ptr_eq
的更多详细信息。
此优化对于未实现 Copy
的数据类型最有用。如果您能以较低成本复制数据,那么将其放在智能指针后面是不值得的。对于像 Vec
、HashMap
和 String
这样数据量可能很大的结构,使用智能指针可能会带来性能提升。
如果子级从未更新值,此优化效果最佳,如果父级很少更新值,效果会更好。这使得 Rc<_>s
成为在纯组件中包装属性值的一个好选择。
但是,必须注意,除非您需要在子组件中自己克隆数据,否则此优化不仅毫无用处,还会增加引用计数的不必要成本。Yew 中的属性已经引用计数,并且内部不会发生数据克隆。
视图函数
出于代码可读性的原因,将 html!
的部分迁移到它们自己的函数中通常是有意义的。这不仅能减少缩进量,从而使代码更具可读性,还能鼓励良好的设计模式 - 特别是围绕构建可组合应用程序,因为这些函数可以在多个地方调用,从而减少了必须编写的代码量。
纯组件
纯组件是不改变其状态的组件,它们只显示内容并向上传播消息到正常的可变组件。它们与视图函数的不同之处在于,它们可以使用组件语法(<SomePureComponent />
)从 html!
宏内部使用,而不是表达式语法({some_view_function()}
),并且根据它们的实现,它们可以被记忆化(这意味着一旦调用函数,它的值就会被“保存”,以便如果它使用相同的参数被多次调用,它不必重新计算其值,而只需返回第一次函数调用中保存的值)——防止对相同的道具进行重新渲染。Yew 在内部比较道具,因此只有在道具发生更改时才会重新渲染 UI。
使用工作区减少编译时间
可以说,使用 Yew 最大的缺点是编译 Yew 应用程序所需的时间很长。编译项目所需的时间似乎与传递给 html!
宏的代码数量有关。对于较小的项目来说,这往往不是什么大问题,但对于较大的应用程序来说,将代码拆分成多个板条箱以最大程度地减少编译器对应用程序所做的每次更改的工作量是有意义的。
一种可能的方法是让你的主板条箱处理路由/页面选择,然后为每个页面制作一个不同的板条箱,其中每个页面可以是一个不同的组件,或者只是一个生成 Html
的大函数。在包含应用程序不同部分的板条箱之间共享的代码可以存储在一个单独的板条箱中,该项目依赖于该板条箱。在最好的情况下,你可以从在每次编译时重新构建所有代码变为仅重新构建主板条箱和你的一个页面板条箱。在最坏的情况下,当你编辑“公共”板条箱中的某些内容时,你将回到起点:编译所有依赖于该常用共享板条箱的代码,这可能是其他所有内容。
如果你的主板条箱太重,或者你希望快速迭代深度嵌套的页面(例如,在另一个页面上呈现的页面),你可以使用一个示例板条箱来创建主页面简化的实现,并另外呈现你正在处理的组件。
减少二进制文件大小
- 优化 Rust 代码
cargo.toml
(定义发布配置文件)- 使用
wasm-opt
优化 wasm 代码
注意:有关减少二进制文件大小的更多信息,请参阅 Rust Wasm Book。
Cargo.toml
Cargo.toml
の [profile.release]
セクションで利用可能な設定を使用して、リリースビルドをより小さく構成できます。
[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
ナイトリー Cargo 構成
Rust と Cargo の実験的なナイトリー機能から追加の利点を得ることもできます。trunk
でナイトリーツールチェーンを使用するには、RUSTUP_TOOLCHAIN="nightly"
環境変数を設定します。その後、.cargo/config.toml
で不安定な rustc 機能を構成できます。不安定な機能のドキュメント、特に build-std
と build-std-features
に関するセクションを参照して、構成を理解してください。
[unstable]
# Requires the rust-src component. `rustup +nightly component add rust-src`
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort"]
ナイトリー Rust コンパイラには、こちらのようなバグが含まれる可能性があり、注意と調整が必要になる場合があります。これらの実験的なオプションは慎重に使用してください。
wasm-opt
さらに、wasm
コードのサイズを最適化できます。
Rust Wasm Book には、Wasm バイナリのサイズを削減する方法に関するセクションがあります: Shrinking .wasm size
- リリースビルドで
wasm
コードをデフォルトで最適化するwasm-pack
を使用します wasm
ファイルにwasm-opt
を直接使用します。
wasm-opt wasm_bg.wasm -Os -o wasm_bg_opt.wasm
yew/examples/ の「minimal」の例のビルドサイズ
注意:wasm-pack
结合了 Rust 和 Wasm 代码的优化。本示例中使用了 wasm-bindgen
,但未进行任何 Rust 大小优化。
使用的工具 | 大小 |
---|---|
wasm-bindgen | 158KB |
wasm-bindgen + wasm-opt -Os | 116KB |
wasm-pack | 99 KB |