- Framework GUI Rust Dioxus 0.5 đơn giản hóa đáng kể quy trình phát triển web·desktop·mobile·fullstack, tập trung vào việc viết lại
dioxus-corevà loại bỏ unsafe - Trong giai đoạn từ 0.4.3 đến 0.5.0, dự án đã bổ sung hơn 100.000 dòng mã và hơn 1.400 commit, với core mới được thay đổi theo hướng loại bỏ lifetime và sự phụ thuộc vào
Scope - Mô hình quản lý trạng thái trước đây xoay quanh
use_state·use_refđược thay bằng APISignalcó thểCopy, giúp giảm gánh nặngClonelặp đi lặp lại trong event handler và future - Với một luồng
dioxus::launchvàdx serve --platform, có thể chạy ứng dụng web, desktop và fullstack, đồng thời CLI tự động truyền build feature phù hợp với nền tảng mục tiêu - Asset hot reload, viết lại hệ thống event, cải thiện rendering trên desktop và cả server function streaming cũng được cập nhật, mở rộng phạm vi áp dụng của một codebase Rust duy nhất
Hướng phát hành của Dioxus 0.5
- Dioxus là thư viện tạo GUI bằng Rust, được dùng để triển khai ứng dụng web, desktop và mobile
- Bản phát hành 0.5 được thiết kế với mục tiêu đơn giản hóa, tăng độ vững chắc và mức độ hoàn thiện theo nhu cầu của cộng đồng
- Các thay đổi chính gồm:
- Viết lại hoàn toàn
dioxus-corevà loại bỏ mã unsafe - Giới thiệu API dựa trên
Signalthay chouse_state,use_ref - Loại bỏ toàn bộ lifetime và trạng thái
cx: Scope - Một hàm
launchduy nhất để khởi động ứng dụng trên mọi nền tảng - Hot reload asset hỗ trợ Tailwind và Vanilla CSS
- Viết lại event để cho phép truy cập native
WebSysevent type - Tích hợp Error Boundary, Server Future và Suspense
- Cải thiện reconciliation trên desktop gấp 5 lần
- Server function streaming và hot reload cho fullstack
- Viết lại hoàn toàn
- Có migration guide dành cho người dùng nâng cấp từ Dioxus 0.4
Loại bỏ lifetime và Scope
- Từ Dioxus 0.1 đến 0.4, các giá trị bên trong component có lifetime
'bump, nhờ đó có thể dùng hook, props và scope trong event listener mà không cần sao chép - Cách này nhìn chung hoạt động tốt trong event handler, nhưng future của Dioxus phải là
'static, nên cầnclonetrước khi chuyển giá trị vào future - Khi xảy ra lỗi lifetime, thông báo thường nói rằng
cxphải sống lâu hơn'staticthay vì chỉ ra hook gây lỗi, dễ gây nhầm lẫn - Dioxus 0.5 loại bỏ
Scopevà lifetime'bump, đồng thời chuyểnElementsang dạng không có lifetime - Giờ đây component có thể nhận props trực tiếp mà không cần tham số scope
- Ví dụ:
fn MyComponent(name: String) -> Element
- Ví dụ:
- Runtime function có thể được dùng trực tiếp không chỉ trong component mà còn bên trong future và event handler
- Khi
Elementtrở thành'static, nó cũng có thể được dùng trong hook hoặc cung cấp qua context API - Thay đổi này tạo nền tảng giúp dễ triển khai các API như virtual list hoặc offscreen rendering
Loại bỏ unsafe trong dioxus-core
- Việc loại bỏ lifetime
'bumpvà scope tạo cơ hội giảm mã unsafe bên trong Dioxus dioxus-core 0.5không còn mã unsafe- Một số dependency vẫn còn một lượng nhỏ unsafe, và nhóm Dioxus có kế hoạch loại bỏ chúng trong chu kỳ phát hành 0.5
- Phần unsafe còn lại được phân loại thành những phần có thể đơn giản loại bỏ hoặc những phần cần thiết do FFI
Quản lý trạng thái dựa trên Signal
- Dioxus 0.5 giới thiệu Signal làm primitive trạng thái cốt lõi của component
- So với
use_statevàuse_ref, Signal có hai ưu điểm:- Luôn có thể
Copy - Không cần subscribe thủ công
- Luôn có thể
-
Trạng thái Copy
Signal<T>làCopyngay cả khi giá trịTbên trong không phảiCopy- Cơ chế này được hiện thực nhờ crate generational-box, được xây dựng mà không cần unsafe
- Khi cần, Signal có thể trở thành
Send+Syncđể chuyển qua các thread - Kết hợp trạng thái Copy,
Send+SyncSignal và component static giúp dễ dàng chuyển trạng thái đến future, event handler, thread và các vị trí cần thiết - Cách dùng bộ nhớ gần như giống 0.4, nhưng không cần
Clonetường minh
-
Subscribe thông minh
- Signal quyết định chi tiết hơn component nào cần chạy lại khi giá trị thay đổi
- Chỉ những component đã đọc giá trị Signal mới được chạy lại
- Các lần đọc trong tác vụ async hoặc event handler không được xem là subscribe để rerun component
- Nếu component cha thay đổi Signal bằng một lần click nút nhưng không trực tiếp đọc giá trị, còn component con mới là nơi đọc giá trị, thì chỉ component con được render lại
- Nhờ cấu trúc này, không còn cần crate quản lý trạng thái riêng Fermi
- Fermi từng cung cấp API tương tự
use_statedùng static làm key - Trong Dioxus 0.5, có thể đặt
GlobalSignaltrong static và dùng nó như Signal thông thường - Signal cũng hoạt động với context API, cho phép chia sẻ trạng thái giữa các component mà không cần hook
use_shared_stateriêng - Khi đọc Signal bên trong các hook như
use_future,use_memo, Signal đó tự động được thêm vào dependency của hook
CSS và asset hot reload
- Dioxus 0.5 triển khai hot reload cho file CSS trong thư mục asset như một phần của việc cải tổ hệ thống asset
- Khi file CSS xuất hiện trong RSX, CLI
dxsẽ theo dõi file đó và stream cập nhật ngay đến ứng dụng đang chạy - Hỗ trợ cho Web, Desktop và Fullstack; hỗ trợ mobile sẽ được bổ sung trong bản cập nhật tập trung vào mobile sau này
- Khi dùng cùng Tailwind watcher, hệ thống cũng hỗ trợ hot reload Tailwind CSS
- Trên VSCode, có thể nhận gợi ý class Tailwind qua custom regex extension
- Có thể stream thay đổi đồng thời đến nhiều thiết bị để hot reload trên toàn bộ thiết bị đích
Viết lại hệ thống event
- Từ khi ra mắt, Dioxus đã dùng synthetic event system để xây dựng API event đa nền tảng
- Synthetic event hữu ích cho việc đồng nhất hành vi event giữa các nền tảng và cho serialize qua mạng, nhưng cũng có giới hạn
- Dioxus 0.5 nay phơi bày kiểu event nền tảng gốc của từng nền tảng và đồng thời cung cấp trait cho API đa nền tảng
- Hai lợi ích chính của thay đổi này là:
- Có thể lấy trực tiếp thông tin cần thiết từ kiểu event của nền tảng hoặc chuyển cho thư viện khác
- Có thể bundle splitting phần mã event mà ứng dụng không dùng đến
- Trong ví dụ hello world, kích thước gzipped giảm khoảng 25%
- Các mẹo tạo bundle nhỏ hơn được đưa vào Dioxus optimization guide
API chạy ứng dụng đa nền tảng
- Dioxus 0.5 giới thiệu API đa nền tảng mới để chạy ứng dụng
- Thay vì import package renderer riêng, chỉ cần bật feature trong crate
dioxusvà gọi hàmlaunchtừ prelude - Một ứng dụng có thể chạy trên các nền tảng sau:
- Desktop:
dx serve --platform desktop - SPA Web:
dx serve --platform web - Fullstack:
dx serve --platform fullstack
- Desktop:
- CLI sẽ tự động truyền build feature phù hợp theo nền tảng mục tiêu
Hệ thống asset beta và Manganis
- Trong Dioxus và ứng dụng web, đường dẫn asset dễ bị lỗi thời, liên kết giữa desktop và web có thể khác nhau, đồng thời nhà phát triển phải tự thêm asset vào bundle
- Asset cũng có thể trở thành nút thắt hiệu năng
- Trong ví dụ hướng dẫn Dioxus Mobile, bản 0.4 mất 7 giây để tải và truyền 9MB tài nguyên
- Hướng dẫn mobile của 0.5 dùng cùng hình ảnh nhưng tải dưới 1 giây và giảm lượng tài nguyên cần thiết xuống còn 1/3
- Dioxus 0.5 giới thiệu hệ thống asset mới manganis
- Tích hợp với CLI để kiểm tra, đóng gói và tối ưu asset của ứng dụng
- API vẫn chưa ổn định nên được phát hành dưới dạng crate riêng
- Khi bọc asset bằng macro
mg!, CLI sẽ tự động nhận diện - Thông tin chi tiết có trong manganis docs
- Trong quá trình phát hành 0.5, nhóm cũng dự định thêm hot reload cho asset manganis
Cải thiện rendering desktop gấp 5 lần
- Dioxus dùng nhiều tối ưu hóa để tạo diff rendering nhanh hơn
- Templates cho phép bỏ qua diff phần tĩnh của macro
rsx! - Trong Dioxus Web, sledgehammer được dùng để áp dụng thay đổi DOM nhanh từ Rust
- Dioxus 0.5 áp dụng cùng cách tiếp cận đó cho việc áp dụng thay đổi qua mạng
- Renderer của Desktop và LiveView giao tiếp thay đổi bằng binary protocol thay vì JSON
- Trong các tác vụ có tải rendering lớn, renderer mới giảm thời gian áp dụng thay đổi lên trình duyệt xuống còn 1/5 và giảm độ trễ còn 1/2
- Benchmark từng khiến renderer liên tục khựng trên Dioxus 0.4 nay chạy mượt trên Dioxus 0.5
Các tiện ích giúp viết component dễ hơn
- Dioxus 0.5 hỗ trợ mở rộng một element cụ thể và bung thuộc tính vào element đó
- Ví dụ: component
ImgPlusmở rộng thuộc tính của elementimgcó thể nhận nguyên các thuộc tính phổ biến nhưwidth,height,src
- Ví dụ: component
- Có thể dùng cú pháp rút gọn khởi tạo struct khi truyền giá trị vào thuộc tính và component
- Có thể viết
classthay vìclass: class
- Có thể viết
- Thuộc tính rút gọn hoạt động với mọi mục triển khai
IntoAttribute, và Signal cũng hưởng lợi từ điều này - Thuộc tính Signal hiện vẫn chưa bỏ qua diffing, nhưng có kế hoạch bổ sung tối ưu hiệu năng này trong chu kỳ phát hành 0.5
- Các thuộc tính trải trên nhiều dòng có thể được hợp nhất
- Nếu thêm giá trị có điều kiện vào cùng thuộc tính
class, chúng sẽ được ghép với dấu cách làm dấu phân tách - Điều này quan trọng với các thư viện như Tailwind, nơi cần parsing ở compile time nhưng vẫn cần xử lý động lúc runtime
- Cú pháp này tích hợp với Tailwind compiler để loại bỏ overhead runtime của các thư viện như
tailwind-merge
- Nếu thêm giá trị có điều kiện vào cùng thuộc tính
Server function streaming và Fullstack
- Dioxus 0.5 hỗ trợ server functions crate mới nhất, có hỗ trợ dữ liệu streaming
- Server function có thể stream dữ liệu tới client hoặc stream dữ liệu từ client lên server
- Có thể tạo server function streaming bằng cách định nghĩa kiểu output và trả về
TextStreamtừ server function - Phù hợp để cập nhật client trong các tác vụ mất nhiều thời gian
- Có ví dụ dùng Kalosm và local LLM để cung cấp chức năng tương tự endpoint OpenAI ChatGPT trên phần cứng phổ thông
- CLI hiện hỗ trợ nền tảng
fullstack, đồng thời cung cấp hot reload và build song song cho client và serverdx servedx serve --platform fullstack
LiveView, asset handler và xử lý file
- Trong Dioxus 0.5, router hoạt động mặc định trong ứng dụng LiveView
- PR liên quan: https://github.com/DioxusLabs/dioxus/pull/1505
- Dioxus Desktop hỗ trợ custom asset handler
- PR liên quan: https://github.com/DioxusLabs/dioxus/pull/1719
- Custom asset handler cho phép stream dữ liệu hiệu quả đến trình duyệt trực tiếp từ mã Rust mà không cần qua JavaScript
- Phù hợp với các giao tiếp băng thông lớn như video streaming
- PR liên quan: https://github.com/DioxusLabs/dioxus/pull/1727
- Có thể truyền trực tiếp dữ liệu gstreamer hoặc webrtc vào webview, giúp giảm nhu cầu tự mã hóa·giải mã frame
- Tính năng kéo-thả file trên desktop cũng được tích hợp native vào hệ thống event
Xử lý lỗi
- Dioxus giúp xử lý lỗi dễ dàng ở component cấp trên thông qua Error Boundary và trait
throw - Cách tiếp cận
throwkết hợp ưu điểm của trạng thái lỗi và trả về sớm - Có thể gọi
throwtrên kiểuResulttriển khaiDebugđể chuyển sang trạng thái lỗi, rồi dùng?để trả về sớm - Component
ErrorBoundarysẽ render component khác khi có lỗi được ném ra từ component con ErrorBoundarycó thể lồng nhau để bắt lỗi ở nhiều cấp trong ứng dụng- Mẫu này hữu ích để xử lý trạng thái lỗi toàn cục mà không cần panic khi gặp lỗi không thể khôi phục hoặc tự quản lý trạng thái cho từng lỗi riêng lẻ
Trải nghiệm phát triển và template
- Dioxus đã giới thiệu hot reload ở bản 0.3, thêm cho Desktop ở 0.4, và bật mặc định trong 0.5
- Khi chạy ứng dụng bằng
dx serve, hot reload được bật mặc định trong chế độ phát triển - Ngay cả khi hot reload không thể áp dụng trên ứng dụng Desktop và cần biên dịch lại toàn bộ, trạng thái của cửa sổ đang mở vẫn được giữ và khôi phục
- Kích thước và vị trí cửa sổ ứng dụng được giữ nguyên
- Giảm tình trạng ứng dụng liên tục che kín màn hình mỗi lần chỉnh sửa
- Template mới được sắp xếp lại để có thể tạo ứng dụng Web, Desktop, Mobile, TUI và Fullstack bằng một lệnh duy nhất
- Ứng dụng mặc định của
dx newđược thay đổi theo hướng gần với create-react-app- Bao gồm assets, CSS và cấu hình triển khai cơ bản
- Bao gồm liên kết tới các tài nguyên hữu ích như dioxus-std, VSCode Extension, tài liệu và tutorial
Dioxus Community và hệ sinh thái
- Dioxus Community đã cập nhật các crate hệ sinh thái quan trọng cho bản phát hành 0.5
- Các crate như icons, charts và thư viện chuẩn dành riêng cho Dioxus đã sẵn sàng để dùng ngay khi 0.5 ra mắt
- Dự án
Dioxus Communitylà một tổ chức GitHub mới nhằm giữ các crate quan trọng luôn được cập nhật ngay cả khi maintainer ban đầu rời đi - Nếu đang xây dựng thư viện cho Dioxus, phía Dioxus có thể hỗ trợ bảo trì và hướng tới duy trì ở mức hỗ trợ “Tier 2” trên thực tế
Các tính năng được lên kế hoạch tiếp theo
- Kế hoạch sau 0.5 bao gồm:
- Ổn định hóa hệ thống asset và tích hợp sâu hơn
- Bundle splitting trực tiếp cho file
.wasmđầu ra cùng lazy component - Islands, resumable interactivity và serialize Signal
- Hợp nhất Server component và LiveView vào Fullstack
- Devtools và framework kiểm thử được cải tiến
- Đại tu toàn bộ Mobile
- Đại tu Fullstack, bao gồm WebSocket, SSE, progressive form...
Xem trước Dioxus-Blitz dựa trên Servo
- Trong “Blitz 2.0” của Dioxus-Blitz, nhóm hướng tới tích hợp Servo để thực hiện WGPU native rendering với cùng CSS engine như khi chạy Firefox
- Nico Burns, tác giả thư viện layout Taffy, đã tham gia toàn thời gian để thúc đẩy công việc này
- Trong bản demo,
google.comđược render trên GPU ở mức 900 FPS - Bản triển khai hiện tại vẫn chưa hoàn chỉnh và việc render
google.comcòn hơi gượng, nhưng đang nhanh chóng tiến gần đến mức có thể sử dụng - Có thể xem kho mã tại https://github.com/jkelleyrtp/stylo-dioxus
Cách đóng góp
- Dự án Dioxus đang tìm kiếm các đóng góp sau:
- Dịch tài liệu
- Thử các “Good First Issues”
- Cải thiện tài liệu
- Đóng góp cho CLI
- Trả lời câu hỏi trong cộng đồng Discord
- Nhóm Dioxus gửi lời cảm ơn tới sự hỗ trợ của cộng đồng trong thời gian còn lại của năm 2024 và kêu gọi cùng giúp thay đổi cách phát triển ứng dụng
1 bình luận
Ý kiến trên Hacker News
Khi bắt đầu làm thì nó ở phiên bản 0.2, và với các thay đổi trong bản 0.5 lần này, có vẻ hầu hết sự phức tạp tôi gặp khi đó đã biến mất. Tôi chưa trực tiếp dùng thử, nhưng việc loại bỏ lifetime và giảm gánh nặng phải clone liên tục có lẽ sẽ khiến trải nghiệm dễ chịu hơn nhiều
Có khá nhiều framework Rust hướng tới UI phản ứng native có thể triển khai lên desktop, web/wasm, mobile, v.v. https://github.com/flosse/rust-web-framework-comparison, nên tôi lo nếu chọn sai thì sẽ phải duy trì một framework bị bỏ bê hoặc phải migration rất đau đớn
Các framework Rust HTTP server cũng từng nhiều tương tự, và giờ có vẻ Axum, Actix, Rocket đang dẫn trước; dòng chảy cộng đồng dường như đang chuyển sang Axum nên tôi cũng tự hỏi liệu chọn Actix có phải sai lầm không. Tôi muốn biết có tín hiệu nào cho thấy Dioxus sẽ thắng không, ngoài cộng đồng lớn, hỗ trợ từ YC và đà phát triển; liệu có chỉ báo nào cho thấy giờ có thể chọn nó không
Tôi cũng muốn biết Leptos và Yew có phải các đối thủ chính không, và vì sao chúng tốt hơn hoặc kém hơn Dioxus. Công ty chúng tôi đã đầu tư nhiều vào Rust, Actix, Bevy, và về sau muốn kết hợp các framework như Bevy và Dioxus để xây client native cho desktop/mobile
Và tôi cũng tò mò tên Dioxus có bắt nguồn từ Deoxys trong Pokémon không. Logo thì gợi cảm giác như vậy, nhưng trong codebase không có tham chiếu nào tới Pokémon
Khoảng 9 tháng trước tôi đã làm một GUI frontend cho sshfs bằng Dioxus, và ấn tượng của tôi là đây là một GUI framework thật sự tuyệt vời cho tới khi đâm vào bức tường là có tính năng nào đó mà nhà phát triển vẫn chưa hoàn thiện
Chia sẻ state giữa các context khác nhau đôi khi cũng khá đau đầu, nhưng mọi GUI framework tôi từng dùng đều như vậy, bất kể ngôn ngữ hay công nghệ nền là gì. Dioxus 0.5 có vẻ là một bước tiến lớn ở điểm này. Blog của tôi render phần lớn HTML bằng Dioxus, và vì không dùng để đẩy tới giới hạn nên nó hoạt động rất tốt
Tuy nhiên cách giải quyết loại bỏ lifetime khiến tôi hơi băn khoăn. generational-box trông giống một kiểu garbage collector của người nghèo, nên tôi tò mò tác động hiệu năng ra sao
Nhân tiện, link
[generational-box]([https://crates.io/crates/generational-box](<https://crates.io/crates/generational-box>))đang bị hỏnguse_hooksở hữu giá trị trong suốt vòng đời component, nên khi component biến mất thì giá trị đó cũng bị drop. Mọi signal vẫn dùnguse_hook, nên vòng đời cũng giống nhau. Thường không khuyến nghị gọiGenerationalBox::new()bên ngoàiuse_hook, vì vậy không có tác động hiệu năngNếu lạm dụng
GenerationalBox::new()trong vòng lặp, rác đó sẽ tồn tại cho tới khi component bị drop, nhưng phần lớn trường hợp người ta sẽ push/pop vào Map hoặc Vec, và khi đó các ngữ nghĩa bộ nhớ thông thường sẽ được áp dụngTôi hiểu nó là một kiểu arena allocation, nhưng không hiểu nó hỗ trợ “copy mà không copy” ra sao, và vì sao mô tả rằng bên trong nó tạo một arena
RefCellcó thế hệ, cònGenerationalBoxlàCopy, lại an toànTôi hiểu có thể tạo con trỏ tới dữ liệu static, nhưng nếu là giá trị không có lifetime static thì sao?
Tham chiếu dữ liệu được giữ trong suốt vòng đời chương trình. generational box cho phép bạn đặt dữ liệu có vòng đời ngắn hơn vòng đời chương trình vào đó, nhưng dữ liệu đó không được chứa tham chiếu. Khi dữ liệu đã đặt vào bị drop, box đó được tái sử dụng cho allocation khác
Cách tiếp cận này rất giống arena theo thế hệ, chỉ khác là dùng box thay vì arena tập trung; đó là lựa chọn để tránh vấn đề khóa. Nếu cố truy cập dữ liệu bằng tham chiếu
Copysau khi nó đã bị drop, thao tác sẽ thất bại với thông báo lỗi tốtCopycó một ý nghĩa cụ thểNếu một type implement trait
Copy, điều đó có nghĩa nó có thể được sao chép bằngmemcpy, và gần với shallow copy hơn là deep copyVì vậy tôi hiểu đây không phải là “copy mà không copy”, mà là cho phép xử lý một type không phải
Copynhư một typeCopy. README nói cần nội dung static, nên với giá trị không có lifetime static thì câu trả lời là “không thể làm như vậy”Tôi thích việc Dioxus lấy nhiều yếu tố đã làm nên thành công của React, đồng thời vẫn nhanh chóng đổi mới và phát hành trên nền tảng đó. Tôi rất mong được dùng thử signals trong bản phát hành này
Tôi công nhận những điều tốt React đã làm cho JS và web, cũng như sức nặng tên tuổi của nó, nhưng nếu năm 2024 có thể thiết kế một ngôn ngữ hoặc DSL từ đầu, tôi không nghĩ code “UI phản ứng” nhất thiết phải trông giống React
Không có ý nói SwiftUI hoàn hảo, nhưng code viết bằng SwiftUI cho cảm giác gọn gàng và được phân tách rõ ràng hơn nhiều so với khi viết code tương tự bằng React
Ưu điểm thực sự của việc dùng JSX cho GUI đa nền tảng chỉ là có thể tái sử dụng các thư viện hiện có dành cho web; còn RSX ngoài việc giúp lập trình viên chuyển kiến thức khái niệm về JSX sang RSX thì có vẻ không có nhiều “giá trị có thể chuyển dịch”. Thà học một paradigm mới được xem là khách quan tốt hơn paradigm React/JSX còn là một sự đánh đổi hợp lý hơn
Tóm lại, sẽ thật tốt nếu có một dự án kiểu “SwiftUI nhưng đa nền tảng”, nhưng hiện vẫn chưa có. Tôi biết @Tokamak/TokamakUI, nhưng nó vẫn còn rất chưa hoàn thiện và có vẻ hoạt động cũng giảm đi
Hiện tại chỉ hỗ trợ ứng dụng desktop native trên Linux/mac/windows, nhưng có kế hoạch hỗ trợ WASM, web và mobile
Nó sẽ trở thành website phi tập trung đầu tiên mà những người thiết lập Freenet nhìn thấy. Nó cũng hơi giống framework web Kotlin Kweb mà tôi đã làm rải rác trong vài năm, đặc biệt là cách xử lý trạng thái và kiểu DSL ánh xạ từ code sang HTML. Đến giờ tôi khá hài lòng
https://freenet.org/
https://kweb.io/
Thực ra tôi là fan của Kotlin, và thích Kotlin DSL cũng như mô hình concurrency của nó
Tauri đặt frontend vào webview, và phải giao tiếp với các hàm Rust native qua ranh giới IPC, giống Electron
Trong Dioxus, code Rust nằm ở phía native, nên các tác vụ như đọc hệ thống file hay websocket không cần IPC. Tauri buộc frontend phải biên dịch sang WASM, và nhiều crate Rust thú vị lại không biên dịch được sang wasm
Thật khó diễn tả việc phát triển đơn giản hơn đến mức nào khi không có ranh giới IPC. Công cụ của Dioxus chỉ nhắm tới Rust, nên có thể đi từ con số 0 đến một
.appđã bundle trong chưa đầy 1 phút. Build mới khoảng 12 giây, bundle mới khoảng 20 giâyDù vậy tôi vẫn rất thích sự linh hoạt mà Tauri mang lại, tức là có thể dùng bất kỳ UI tương thích web nào làm frontend, và cũng có thể dùng Dioxus bên trong một app Tauri
Việc Dioxus trực tiếp đề cập trong README là tốt, nhưng tôi cũng tò mò về trải nghiệm thực tế của những người đã dùng cả hai
Tôi đã thử làm một app desktop đồ chơi bằng Tauri, và đã kiểm tra xem IPC có đủ nhanh để frontend web cập nhật và xử lý theo từng lần gõ phím mà không bị trễ hay không; câu trả lời là “có”. Còn việc có thể gửi một file lớn từ frontend sang tầng Rust rồi trả lại frontend theo từng lần gõ phím hay không thì, ít nhất với cách triển khai ngây thơ của tôi, câu trả lời là “không”
Cả Tauri lẫn Dioxus đều có nhiều use case ổn, và trong một số trường hợp Dioxus có vẻ tốt hơn. Tôi muốn nghe các câu chuyện so sánh kiểu “dự án của chúng tôi chọn Dioxus hoặc Tauri vì X và Y”. Dioxus trông thật sự rất hay nên tôi mong được thử
stylo là phần được chia sẻ giữa Servo và Firefox. Về dài hạn chúng tôi muốn chuyển mọi người sang renderer WGPU, nhưng nó vẫn còn khá sơ khai, và nhiều công ty dùng Dioxus thực tế hiểu rằng webview là một giải pháp đủ tốt cho khoảng 90% app
Tôi hiểu đôi khi mọi người dùng
unsafequá dễ dãi, nhưng thư viện chuẩn cũng đầyunsafe, và việc vạch ranh giới ở đó đôi khi trông như vẽ một đường trên cátCó ba chỗ đang dùng. Một số sửa đổi FFI trên iOS, phần triển khai để cho phép cú pháp gọi hàm với signal, và phần implement Send/Sync cho ID dùng con trỏ làm hash
Cái cuối, giờ nhìn lại thì có lẽ có thể loại bỏ nếu thay bằng
usizeunsafeDù vậy, việc tác giả crate đặt mục tiêu loại bỏ
unsafekhỏi crate của mình không nhất thiết là một quyết định tệNhững tác giả crate muốn loại bỏ mọi
unsafethường là để giảm gánh nặng niềm tin mà người dùng phải chịu. Tôi nghĩ đó là sức mạnh của từ khóaunsafe. Thực ra có lẽ nó nên được tách thành blocktrust_mevà hàmcheck_yourselfunsafegiới hạn cuộc thảo luận về an toàn bộ nhớ vào những vị trí rất hẹp và có thể audit trong code, đồng thời tạo ra một cuộc thảo luận mới, có thể quản lý được, về niềm tinuse*cho hook API, nhưng tôi tò mò vì sao trong Dioxus hàm tạo signal mới lại làuse_signallet mut count = use_signal(|| 0);chẳng phải là lời gọi tạo signal mới sao? Signal không được tạo lại mỗi lần render, và đó chính là điểm cốt lõi của signalTrong SolidJS, signal được tạo bằng createSignal như
const [count, setCount] = createSignal(0), cách này dễ hiểu hơn nhiềuTên API rất quan trọng. Vì state hook hoạt động khác đi và cũng có thể phát sinh nhu cầu bổ trợ như
useMemo. Tôi tò mò liệu có lý do nào Dioxus chọn tênuse_signalngoài việc muốn trông gần với React khôngNó gần với Preact hơn là Solid
Các tối ưu hóa bao gồm tách các mảnh động của UI thành “diff bin” riêng, memoization mặc định, và việc signal ngầm đánh dấu thuộc tính là dirty/managed