Loco.rs 项目结构分析

Loco.rs 通过命令行可快速生成模版项目,这里对生成的模版项目结构进行分析,以便理解 Loco.rs 工作原理,并为整合其他组件做准备。

项目启动

安装 CLI 工具:

1
2
cargo install loco
cargo install sea-orm-cli

使用 CLI 工具交互式创建模版项目

1
loco new

启动项目

1
cargo loco start

完成后将在 localhost:5150 上启动服务,通过浏览器访问即可打开页面。

项目结构

生成的 loco.rs 模版项目以 Cargo Workspace 形式组织。顶层 Cargo.toml 定义了 workspace. 在 workspace 中引入了 loco-rs 并指定版本,成员中引用 loco-rs 可统一使用该版本避免不同 crate 间发生版本冲突。同时将顶级目录本身作为一个 crate. 在 dependencies 中引入 serde、tracing 等依赖项。dev-dependencies 中引入开启 testing 特性的 loco-rs 等只在测试中使用的依赖项。同时,为顶层 crate 指定 src/bin/main.rs 作为入口文件。

assets 子目录中,包含 i18n、static、views 目录,存放项目中使用的资源文件。i18n 目录中包含 shared.ftl 文件,用于存放共享的国际化资源。在国际化代码目录中的 main.ftl 文件则包含对应国际化代码下的国际化资源。views 目录中则存放项目中使用的页面模版文件。static 则作为项目的静态资源,请求对应的资源文件时,会从该目录中查找并返回。

config 子目录中,保存以环境命名的 .yaml 配置文件。项目运行时默认使用 development 环境配置,读取 development.yaml 文件。运行时使用 –environment test 参数可切换为 test 环境,此时使用 test.yaml 文件。

examples 子目录是 Cargo 的标准功能,用于存放示例代码。Loco.rs 在其中预置了 playground.rs 文件,可用于编写实验性代码进行快速验证。此时就可以通过 cargo run –example playground 运行示例代码。同时,.cargo/config.toml 文件为这一命令指定了 playground 别名,因此可通过 cargo playground 简化运行命令。

migration 子目录也作为 crate,导出 Migrator 管理项目中的数据库迁移。该目录作为一个 crate,拥有 Cargo.toml、src/lib.rs 这些作为 crate 的必要文件。lib.rs 定义了 Migrator 结构体并实现 MigratorTrait trait. 在实现中引入其他文件中定义的迁移。

tests 子目录是 Cargo 的标准功能,用于存放测试代码。其中通过 mod.rs 将 tests 目录定义为一个模块,并引用内部其他子目录。从而将其中的各项测试代码加入测试范围,通过 cargo test 整合执行。

src 子目录作为项目的核心部分,包含 lib.rs 整合内部各模块。bin/main.rs 作为项目二进制入口,使用 tokio 启动应用的异步运行时。应用逻辑 App 和数据库迁移 Migrator 作为范型参数传入 Loco.rs cli 并由 loco.rs 整合全流程并启动。

主模块结构

src/bin/main.rs 是二进制入口,引用 lib.rs 导出的模块,使用自定义的 App、Migrator 结构体作为 Loco.rs CLI 的范型参数,应用执行时启动 CLI,在 CLI 执行中调用 App、Migrator 实现的 trat. src/app.rs 定义 app 模块,导出实现 Hooks trait 的 App 结构体。

Hooks::boot 钩子引入了 Migrator 范型,同样使用 MigratorTrait::migrations 钩子返回 MigrationTrait 的数组,每个 MigrationTrait 提供 up、down 函数,实现数据库的版本化控制。

Hooks::initializers 钩子返回项目中需要使用的初始化器列表,这些初始化器列表默认放在 src/initializers 目录中。在服务器渲染模版下,定义了 view_engine 初始化器,在 Initilizer::after_routes 钩子中进行模版引擎的初始化。在定义的 i18n 目录 assets/i18n 存在时,加载其中的 i18n 资源和共享资源作为资源包,并基于该资源包构建 tera 渲染引擎,将 t 函数注入渲染引擎中。i18n 目录不存在时则构造默认的 tera 渲染引擎。完成 tera 渲染引擎构造后,将引擎包装为中间件加入 Axum 路由中。

Hooks::routes 钩子返回应用提供的 Axum 路由,添加 controller 后需要将对应的 controller::routes 返回的路由全部加入全局 Axum 路由中。默认应用提供了 src/controllers/auth.rs 文件,导出 routes 函数返回文件中提供的全部路由端点。其中定义的处理器函数全部返回 Result<Response>,在返回 JSON 的端点上,views/ 中的模块定义响应结构和视图渲染函数,返回时调用 views 内的函数或构造其中的结构体实例。

Hooks::connect_workers 钩子注册 src/workers 中的 worker 模块。

Hooks::register_tasks 钩子注册 src/tasks 中的 task 模块。

Hooks::truncate 钩子定义数据库清空操作,通过调用 truncate_table 或其他函数对数据进行清理。

Hooks::seed 钩子定义数据初始化操作,内部调用 db::seed 函数,传入 src/models/_entities 中定义的数据库模型实体和 src/fixtures 中的 yaml 文件初始化表数据。

src/data 中的模块定义数据模型,并提供加载函数。数据读取时从 data 目录中取文件。

src/mailers 中的模块提供邮件发送能力。邮件的各部分、模版都放在其中的子目录内。

src/models 提供应用的充血模型。直接目录中的模块实现大多业务逻辑,src/models/_entities 中定义数据库模型实体。

测试模块

tests 目录存放应用的测试模块。