开门见山,这是我开源的绣化版本bestofjs—— Best of RS!
Github: github.com/zhiyanzhaij…
官网: bestofrs.org
已上线稳定运行一个多月,目前文档、CI齐全,所以各平台做下宣传。
Preview预览
架构介绍
一个基于 Rust 的
Clean & Hexagonal Doamin Driven Design架构, 结合dioxus全栈。
Notice: 本文档所用图表均由Excalidraw绘制, 在此鸣谢。
Clean 架构
先看项目分层:
crates/
- adapters/ # Clean Core
- app/ # Clean Core
- domain/ # Clean Core
- infra/ # Clean Core
- ui/ # User Interface
- worker/ # User Interface
本项目架构参考 axum-clean-architecture by @Thodin,并结合了 Dioxus fullstack 的工程实践。
核心依赖方向:
domain <- app(application) <- adapter <- infra(infrastructure) <- user interface
Clean Core(DDD核心)
1. Domain Layer(crates/domain/src)
Tree图
crates/domain/src
├── auth
├── error.rs
├── lib.rs
├── project
├── repo
└── snapshot
Layer 构成与职责
auth / project / repo / snapshot:按业务子域划分的领域模型error.rs:领域级错误语义lib.rs:领域模块导出边界
Domain层承载领域语义与业务不变式,只关心领域建模,不关心业务编排与技术实现。
典型单元:以 project 为例
crates/domain/src/project
├── entity.rs (实体)
├── event.rs (领域事件)
├── mod.rs
└── value_object.rs (值对象)
2. Application Layer(crates/app/src)
Tree图
crates/app/src
├── app_error.rs
├── auth
├── backup
├── common
├── lib.rs
├── prelude.rs
├── project
├── repo
└── snapshot
Layer 构成与职责
common、app_error.rs:跨 use case 的通用业务逻辑与统一错误语义auth / backup / project / repo / snapshot:不同领域用例(use cases)模块prelude.rs:应用层常用导出
Application层负责业务编排(Use Cases),通过端口抽象依赖外部能力,不直接依赖具体基础设施实现。
典型单元:以 project 为例
crates/app/src/project
├── command.rs (CQRS - read用例)
├── event_handler.rs (领域事件驱动编排)
├── impls (充血模型实现,Rich Domain Model)
├── mod.rs
├── port.rs (Hexagonal Port)
└── query.rs (查询用例)
3. Adapter Layer(crates/adapters/src + crates/ui/src/IO)
Tree图
crates/adapters/src
├── auth
├── clock.rs
├── github.rs
├── lib.rs
├── persistence
└── prelude.rs
Layer 构成与职责
persistence:存储适配实现auth:鉴权/授权相关适配github.rs:外部 API 适配clock.rs:时间能力适配
Adapter层负责技术编排与边界转换,把 Application ports 落地为具体实现。
补充:HTTP endpoint 的实现代码位于 crates/ui/src/IO。这是“物理位置在 ui,逻辑归属在 Adapter”的工程布局。
典型单元:以 persistence/psql 为例
crates/adapters/src/persistence/psql
├── backup.rs (数据备份实现)
├── db.rs (数据库连接实现)
├── mod.rs
├── project_repo.rs (Project 仓储实现)
├── repo_repo.rs (Repo 仓储实现)
├── repo_tag_repo.rs (Tag 仓储实现)
├── runtime.rs (运行时装配)
└── snapshot_repo.rs (Snapshot 仓储实现)
4. Infrastructure Layer(crates/infra/src)
Tree图
crates/infra/src
├── config
├── lib.rs
└── setup.rs
Layer 构成与职责
config:配置模型与配置来源setup.rs:装配入口,负责初始化与依赖注入lib.rs:基础设施模块导出
Infrastructure层只做系统装配与启动准备,不承载业务规则。
典型单元:以 config 为例
crates/infra/src/config
├── mod.rs (配置模块导出)
├── settings.rs (配置结构定义)
└── toml (环境配置文件目录)
User Interface(表现层)
Worker 与 UI 同属 User Interface,但交互对象不同:
UI面向用户交互界面Worker面向任务调度与后台执行
1. UI crate(crates/ui/src)
Tree图
crates/ui/src
├── IO
├── components
├── impls
├── js
├── lib.rs
├── main.rs
├── root
└── types
内容
- `main.rs`:UI/Web 入口与服务启动入口(fullstack)
- `root`:页面布局与Router
- `components`:可复用 UI 组件(目前,出于KISS原则考虑,我将页面组件也放入其中,受影响于Next.js的App Router组织风格)
- `types` 前端viewmodel数据结构
- `impls / js`:前端侧实现细节
Notice:IO 目录虽物理上位于 ui,但本质逻辑为HTTP endpoint adapter的axum实现,在架构归属上属于 Adapter。
参考下图:
SSR Fullstack的核心
Dioxus v0.7.0+ 版本提供了非常便捷的#[post], #[get]等宏,这些宏在提供无缝的fullstack体验的前提下,又保证了代码整洁。
具体的Fullstack原理请参考Dioxus官方文档。
为了更优雅的SSR实现,我根据以往的前端工程经验,创建了
面向复杂ui组件的mod-like样板:
crates/ui/src/components/**/exampleComp/
├── mod.rs #组件
├── skeleton.rs #loading fallback
├── error.rs #错误fallback
├── hook.rs #私有hook
├── context.rs #私有context
├── style.css #若tailwind样式不便
├── (optional)sub-Comp/ #若有子组件,则样板递归
并封装IOCell组件收敛ssr处理逻辑。
还有最简单的纯组件样板,compName.rs, 这个没有特别点,不做展开。
2. Worker crate(crates/worker/src)
Tree图
crates/worker/src
└── main.rs
内容
依赖core层功能的快捷应用,当前仅使用到snapshot领域下一个小的快照功能。略。
为什么做 Best Of RS?
- 作者本身于
bestofjs.org受益良多,在写rust的时候一直想,想着想着就有个这么个点子 - 离职期间,想挖掘下Dioxus的潜力,落地一下DDD, 一拍即合,所以
Best Of RS出来了(PS:求个💼,请github邮箱联系~♥️)
为什么宣传?
- 求Stars要饭
- 普及DDD & cleanDDD
- 普及Rust & Dioxus & WASM
欢迎使用Best Of RS, 如果有所帮助, Star秋梨膏!Orz!!!!