Giới Thiệu
Nếu bạn đã từng làm việc với Tauri, có lẽ bạn đã sử dụng macro tauri::command
, nhưng sau một vài lệnh, bạn nhận ra rằng bạn cần phải viết từng hàm một cách thủ công trong invoke_handler
, điều này có vẻ khó chịu nhưng chấp nhận được.
Tuy nhiên, khi dự án của tôi phát triển, việc quản lý hàng trăm lệnh trở nên khó khăn hơn; việc viết chúng, nhớ rằng mình đã viết chúng, thậm chí việc sửa đổi tên hàm cũng thật phiền phức. Sau vài tuần, tôi tình cờ phát hiện ra specta
, một crate Rust cho phép tôi chuyển Struct thành các loại TS, và các hàm với các tham số đúng, v.v...
NHƯNG nỗi khổ lại đến khi tôi nhận ra rằng tôi phải viết lại tất cả tên hàm mà tôi đã có trong một invoke_handler
khác, điều này có thể được giải quyết bằng cách sao chép và dán, nhưng tôi đã đủ chán với tất cả mã lệnh rườm rà này và việc mã của tôi trở nên dài hàng trăm dòng vì một điều đơn giản như vậy, vì vậy tôi quyết định viết một crate Rust nhỏ, tauri-helper
, để giúp chúng ta, các nhà phát triển, viết mã Rust trong Tauri một cách nhanh chóng và không cần tất cả những dòng mã vô nghĩa này.
Vấn Đề Gặp Phải
Khi xây dựng tauri-helper
, tôi đã gặp phải một số vấn đề trong Rust làm cho việc phát triển trở nên khó khăn hơn:
-
Giới hạn của Macro: Tiếc là, các macro trong Rust không thể biết vị trí chính xác của một hàm trong một module hoặc workspace. Điều đó có nghĩa là nếu tôi muốn chuyển các hàm xung quanh, tôi phải nhập khẩu toàn bộ module, ví dụ:
use some_module::*;
. Điều này làm cho việc viết các macro thu thập trở nên phức tạp hơn mong đợi, mặc dù trong tương lai gần sẽ có khả năng làm điều đó mà không cần nhập toàn bộ module, nhưng hiện tại vẫn đang trong phiên bản nightly và tôi muốn tránh điều đó. -
Nhiều Workspaces: Việc thu thập các lệnh từ nhiều crate trong một workspace trở nên lộn xộn. Mỗi crate có các module và đường dẫn riêng, vì vậy tôi phải làm cho các macro nhận biết workspace và xử lý việc phát hiện hàm chéo giữa các crate để nhận biết mọi thay đổi đối với một hàm hoặc việc tạo ra một hàm để có thể ghi lại nó.
-
Cấu trúc tệp và
build.rs
: Để tự động tạo danh sách lệnh, tôi đã viết các tệp được tạo trong một thư mục riêng bằng cách sử dụngbuild.rs
. Nó hoạt động, nhưng tôi phải quản lý cẩn thận các đường dẫn và đảm bảo mọi thứ được đồng bộ khi các hàm di chuyển hoặc được đổi tên.
Mỗi thách thức này đều yêu cầu thiết kế và thử nghiệm cẩn thận để làm cho tauri-helper
đáng tin cậy và dễ sử dụng cho những người khác, vì đó chính là mục tiêu của crate này.
Cách Sử Dụng Tauri-Helper
Khi tôi giải quyết được các vấn đề phát triển, việc sử dụng crate trở nên đơn giản hơn nhiều và giúp Tauri dễ sử dụng hơn:
Cài Đặt
Thêm tauri-helper
vào tệp Cargo.toml
của bạn:
toml
[dependencies]
tauri-helper = "0.1.4"
Nếu bạn muốn sử dụng macro WithLogging
với tracing
, hãy bật tính năng tracing
:
toml
[dependencies]
tauri-helper = { version = "0.1.4", features = ["tracing"] }
Sau đó thêm nó vào [build-dependencies]
:
toml
[build-dependencies]
tauri-helper = "0.1.4"
QUAN TRỌNG
Trước khi sử dụng bất kỳ việc thu thập lệnh nào, bạn phải thêm đoạn mã này vào tệp build.rs
:
rust
fn main() {
tauri_helper::generate_command_file(tauri_helper::TauriHelperOptions::default());
tauri_build::build();
}
Và sau đó hãy chắc chắn rằng workspace của bạn là chính xác và đã định nghĩa crate hiện tại trong Cargo.toml
của bạn như sau:
toml
[workspace]
members = [
".",
"local-crates/some-commands1",
"local-crates/some-commands2",
"local-crates/some-commands3",
]
Đừng quên thêm
.
như một thành viên, nếu không crate sẽ không thể lấy các lệnh từ crate mặc định.
Cách Sử Dụng
Thu Thập Lệnh
Ghi chú các hàm lệnh Tauri của bạn bằng cách sử dụng #[auto_collect_command]
để tự động thu thập chúng:
rust
#[tauri::command]
#[auto_collect_command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
Tạo một lệnh gọi tauri::generate_handler!
:
rust
tauri_collect_commands!();
Tạo một lệnh gọi tauri_specta::collect_commands!
:
rust
specta_collect_commands!();
Lưu Ý
Nếu bạn không muốn phải ghi chú mỗi lệnh với #[auto_collect_command]
, bạn có thể làm điều này trong build.rs
:
rust
fn main() {
tauri_helper::generate_command_file(tauri_helper::TauriHelperOptions::new(true));
tauri_build::build();
}
Điều này sẽ yêu cầu script build lấy mọi tauri_command
có sẵn trong mọi thành viên của workspace.
Điều này không được khuyến cáo vì có thể dẫn đến việc thêm các hàm không có ý định được xuất khẩu.
Nếu workspace của bạn chứa nhiều crate, bạn phải xuất tất cả các hàm trong tệp gốc (lib.rs
) của mỗi crate.
Ví Dụ
Trong my_commands.rs
:
rust
#[tauri::command]
#[auto_collect_command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
Trong lib.rs
:
rust
pub mod my_commands;
pub use my_commands::*;
Lưu Ý: Điều này là cần thiết vì tính năng cho phép truy xuất đường dẫn module đầy đủ vẫn chỉ có sẵn trong phiên bản nightly của Rust.
Ví Dụ Hoàn Chỉnh
Dưới đây là một ví dụ hoàn chỉnh về việc sử dụng tauri_helper
trong một ứng dụng Tauri:
rust
#[tauri::command]
#[auto_collect_command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
#[tauri::command]
#[auto_collect_command]
fn calculate_sum(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let builder: tauri_specta::Builder = tauri_specta::Builder::<tauri::Wry>::new()
.commands(specta_collect_commands!());
#[cfg(debug_assertions)]
builder
.export(
Typescript::default().bigint(specta_typescript::BigIntExportBehavior::Number),
"../src/bindings.ts",
)
.expect("should work");
tauri::Builder::default()
.invoke_handler(tauri_collect_commands!())
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Kết Luận
Việc tạo ra tauri-helper
không dễ dàng như tôi mong đợi, đặc biệt là cho một dự án đầu tiên, các macro Rust, workspaces đa crate, và việc tạo mã tại thời điểm build đều gây ra những vấn đề lớn trong quá trình phát triển. Nhưng giải quyết chúng đã dẫn đến một crate nhỏ, mạnh mẽ giúp đơn giản hóa ít nhất một chút việc thu thập lệnh trong các dự án Tauri.
Nếu bạn đang xây dựng ứng dụng Tauri và cảm thấy chán ngán với mã lệnh rườm rà, tauri-helper
cho phép bạn viết mã Rust một cách hiệu quả trong khi vẫn giữ cho việc đăng ký lệnh tự động và có tổ chức, giúp bạn tránh được tình trạng mã lib.rs
dài hàng ngàn dòng thật đáng sợ.
Chỉ một lưu ý nhỏ cho các nhà phát triển Rust: với Rust 1.90.0, cargo publish --workspace
đã được giới thiệu, điều này làm cho việc xuất bản các workspaces đa crate dễ dàng hơn nhiều, giúp đơn giản hóa khá nhiều việc xuất bản các workspace đa crate và sẽ làm cho tauri-helper
trở nên hữu ích hơn nữa vì giờ đây bạn có thể tạo ra nhiều crate mà không gặp phải vấn đề xuất bản. Điều này không quan trọng cho việc sử dụng crate, nhưng đó là một cải tiến chất lượng cuộc sống tốt cho các nhà phát triển quản lý các dự án đa crate.