vite-rs 目前还不支持 debug 模式,但为了方便开发,使用约定大于配置的方式也可以轻松实现。
主要实现方式是把axum模板中静态资源请求按规则转发到 vitejs 启动的开发服务上就行了。
当前实现对 vite-rs 没有任何改动,后期官方支持 debug 模式后,当前实现也可以优雅替换。
Vite 资源管理模块
本模块提供了与 Vite 集成的资源文件管理功能,支持 Axum 框架和 Askama 模板引擎。
Axum 接入方式
1. 基本设置
use vite_rs_axum_0_8::ViteServe;
use vite::AssetFiles;
use vite::static_assets_router;
#[derive(vite_rs::Embed)]
#[root = "./app"]
struct Assets;
// 在 main 函数中
#[cfg(debug_assertions)]
let _guard = Assets::start_dev_server(true);
let vite_serve = ViteServe::new(Assets::boxed());
let app = Router::new()
.route("/", get(handle_index))
.merge(static_assets_router(vite_serve));
2. 在模板中使用
use askama::Template;
use vite::AssetFiles;
#[derive(Template)]
#[template(path = "index.html")]
struct IndexTemplate {
assets: AssetFiles,
}
async fn handle_index() -> impl IntoResponse {
let template = IndexTemplate {
assets: AssetFiles::default(),
};
Html(template.render().unwrap())
}
3. 模板文件示例(Askama)
<!DOCTYPE html>
<html>
<head>
{% for css_file in assets.css_files %}
<link rel="stylesheet" href="{{ css_file }}" />
{% endfor %}
</head>
<body>
<!-- 内容 -->
{% for js_file in assets.js_files %}
<script type="module" src="{{ js_file }}"></script>
{% endfor %}
</body>
</html>
默认文件约定名称
Debug 模式(开发环境)
-
JS 入口文件:
/main.js- 支持的文件名(按优先级):
-
main.js/main.ts/main.tsx -
index.js/index.ts/index.tsx
-
- 支持的文件名(按优先级):
-
CSS 文件: 通过 JS 中的
import './style.css'加载- 不需要单独的
<link>标签 - CSS 文件会被 Vite dev server 自动处理并支持 HMR
- 不需要单独的
Release 模式(生产环境)
-
JS 文件: 从
manifest.json自动读取编译后的路径- 入口文件: 优先查找
isEntry: true的条目 - 如果没有,查找常见入口文件名(
main.js,main.tsx,index.js等) - 自动包含所有静态导入的依赖文件
- 入口文件: 优先查找
-
CSS 文件: 从
manifest.json自动读取- 优先从入口文件的
css字段获取 - 如果没有,查找独立的 CSS 条目
- 优先从入口文件的
项目结构要求
project/
├── src/
│ ├── main.rs
│ └── vite.rs # 本模块
├── app/ # 前端代码目录(固定约定)
│ ├── main.js # JS 入口文件(推荐)
│ ├── style.css # CSS 文件(在 main.js 中 import)
│ └── vite.config.ts
└── templates/ # Askama 模板目录
└── index.html
使用示例
使用默认配置(推荐)
let assets = AssetFiles::default();
自定义 manifest 加载器(Release 模式)
let assets = AssetFiles::with_manifest_loader(|| {
Assets::get(".vite/manifest.json")
.and_then(|file| std::str::from_utf8(&file.bytes).ok().map(|s| s.to_string()))
});
使用 new 方法
// Debug 模式:使用默认值
let assets = AssetFiles::new(None);
// Release 模式:使用自定义加载器
let assets = AssetFiles::new(Some(|| {
// 从 Assets 或其他来源读取 manifest
Some(manifest_content)
}));