Skip to main content
Version: Next

优化 & 最佳实践

使用智能指针

注意:如果您对本节中使用的某些术语感到困惑,Rust 手册中有一个有用的关于智能指针的章节

为了避免在重新渲染时克隆大量数据以创建 props,我们可以使用智能指针,只克隆对数据的引用而不是数据本身。如果您在 props 和子组件中传递与相关数据的引用而不是实际数据,您可以避免在需要修改数据的子组件中克隆任何数据,您可以使用 Rc::make_mut 来克隆并获得要更改的数据的可变引用。

这在 Component::changed 中带来了更多好处,可以确定 prop 更改是否需要组件重新渲染。这是因为可以比较指针地址(即数据存储在机器内存中的位置)而不是数据的值;如果两个指针指向相同的数据,则它们指向的数据的值必须相同。请注意,反之可能不成立!即使两个指针地址不同,底层数据仍可能相同 - 在这种情况下,您应该比较底层数据。

要进行此比较,您需要使用 Rc::ptr_eq 而不仅仅使用 PartialEq(在使用相等运算符 == 比较数据时自动使用)。Rust 文档有关于 Rc::ptr_eq更多细节

这种优化对于不实现 Copy 的数据类型最有用。如果您可以廉价地复制数据,则没有必要将其放在智能指针后面。对于可能是数据密集型的结构,如 VecHashMapString,使用智能指针可能会带来性能改进。

如果值从不被子组件更新,则此优化效果最佳,如果父组件很少更新,则效果更佳。这使得 Rc<_> 是在纯组件中包装属性值的一个不错的选择。

但是,必须注意,除非您需要在子组件中自己克隆数据,否则这种优化不仅是无用的,而且还增加了不必要的引用计数成本。Yew 中的 props 已经是引用计数的,内部不会发生数据克隆。

渲染函数

出于代码可读性的原因,将 html! 的部分重复代码迁移到专门分割出来的函数中通常是有意义的。这不仅使您的代码更易读,减少了代码缩进,而且还鼓励良好的设计模式——特别是围绕构建可组合应用程序,这些函数可以在多个地方调用,从而减少代码量。

纯组件

纯组件是不会改变其状态的组件,只显示内容并将消息传播到普通的可变组件。它们与视图函数的不同之处在于,它们可以在 html! 宏中使用组件语法(<SomePureComponent />)而不是表达式语法({some_view_function()}),并且根据其实现,它们可以被记忆化(这意味着一旦调用函数,其值就会被“保存”,因此如果多次使用相同的参数调用它,则不必重新计算其值,只需从第一个函数调用返回保存的值)- 防止相同的 props 重新渲染。Yew 在内部比较 props,因此仅在 props 更改时重新渲染 UI。

使用工作区减少编译时间

Yew 的最大缺点是编译所需的时间很长。编译项目所需的时间似乎与传递给 html! 宏的代码数量有关。对于较小的项目,这似乎不是什么问题,但对于较大的应用程序,将代码拆分到多个 crate 中以最小化编译器为应用程序所做的工作量是有意义的。

一种可能的方法是使您的主 crate 处理路由/页面选择,然后为每个页面创建一个不同的 crate,其中每个页面可以是不同的组件或只是生成 Html 的大函数。存储在包含应用程序不同部分的 crate 之间的代码可以存储在项目依赖的单独 crate 中。在最理想的情况下,您从在每次编译时重新构建所有代码到仅重新构建主 crate 和一个页面 crate。在最坏的情况下,如果您在“common” crate 中编辑了某些内容,您将回到起点:编译依赖于该常用共享 crate 的所有代码,这可能是其他所有内容。

如果您的主 crate 太重,或者您想快速迭代一个深度嵌套的页面(例如。在另一个页面上渲染的页面),您可以使用示例 crate 创建主页面的简化实现,并额外渲染您正在处理的组件。

减小二进制文件大小

  • 优化 Rust 代码
  • cargo.toml(定义发布配置文件)
  • 使用 wasm-opt 优化 wasm 代码

注意:有关减小二进制文件大小的更多信息,请参阅Rust Wasm 手册

Cargo.toml

可以使用 Cargo.toml[profile.release] 部分中的可用设置来配置发布构建为更小。

[profile.release]
# 让二进制文件尺寸更小些
panic = 'abort'
# 优化整个代码库(优化更好,但构建速度也会更慢)
codegen-units = 1
# 优化尺寸(更激进的做法)
opt-level = 'z'
# 优化尺寸
# opt-level = 's'
# 使用程序整体分析时进行链接时优化
lto = true

开发版 Cargo 配置

您还可以从 Rust 和 cargo 的实验性开发版功能中获得额外的好处。要使用 trunk 的开发版工具链,请设置 RUSTUP_TOOLCHAIN="nightly" 环境变量。然后,您可以在 .cargo/config.toml 中配置不稳定的 rustc 功能。请参考[不稳定功能]的文档,特别是关于build-stdbuild-std-features的部分,以了解配置。

.cargo/config.toml
[unstable]
# 需要 rust-src 组件。`rustup +nightly component add rust-src`
build-std = ["std", "panic_abort"]
build-std-features = ["panic_immediate_abort"]
警告

开发版 Rust 编译器可能包含错误,例如这个例子,需要偶尔关注和调整。请谨慎使用这些实验性选项。

wasm-opt

此外,可以优化 wasm 代码的大小。

Rust Wasm 手册中有关于减小 Wasm 二进制文件大小的部分:缩小 .wasm 大小

  • 使用 wasm-pack,默认情况下会优化发布构建中的 wasm 代码
  • 直接在 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-bindgen158KB
wasm-bindgen + wasm-opt -Os116KB
wasm-pack99 KB

进一步阅读