# Stash Stash 是一个用 Rust 编写的本地静态页面托管工具。编译后的 React 控制台会被内嵌进二进制, 所以发布物只有一个 `stash` 可执行文件,不需要额外部署前端静态资源。 它能做两件事:托管目录下的多个静态前端项目、给控制台提供同源 JSON / SSE 接口。 ## 快速开始 ```bash # 1. 先构建前端(dist 会被内嵌,缺了它 cargo build 会直接失败) cd stash-web npm install npm run build cd .. # 2. 编译并运行 cargo run # 托管 ./public,监听 127.0.0.1:8080 # 自定义目录 / 端口 / 对外暴露 cargo run -- --root ./sites --port 3000 cargo run -- --root ./sites --host 0.0.0.0 --port 3000 ``` 启动后打开终端里打印的地址即可,例如 `http://127.0.0.1:8080/`。 默认托管目录 `./public` 不存在时会自动创建。 环境要求: - Rust 工具链(2024 Edition) - Node.js 24,推荐用 [Volta](https://volta.sh/) 管理;`stash-web/package.json` 里已用 `volta` 字段固定版本 ## 工作方式 请求按下面的顺序命中: | 路径 | 处理方式 | | --- | --- | | `/api/*` | JSON / SSE 接口 | | `/`、`/index.html` | 内嵌前端的 `index.html`(`no-cache`) | | `/assets/**` | 内嵌前端的静态资源(文件名带 hash,长缓存) | | `/favicon.svg` | 内嵌前端根目录文件 | | 其他路径 | `ServeDir` 托管 `--root` 目录,目录自动补 `index.html` | | 仍未命中 | 内置 404 页面(显示请求路径) | 托管目录下的每个一级子目录,只要包含 `index.html` 或 `index.htm`,就会被识别为一个项目, 通过 `/<目录名>/` 访问。目录名会做 URL 路径段编码。 ## 目录结构 ```text . ├── Cargo.toml # 单 crate(lib + bin),依赖清单 ├── Cargo.lock ├── build.rs # 把 stash-web/dist 同步到 $OUT_DIR/web ├── src/ # Rust 后端 │ ├── main.rs # CLI 参数、启动横幅、停机信号 │ ├── lib.rs # 库导出 │ ├── config.rs # 服务配置 │ ├── error.rs # 错误类型与 JSON 错误响应 │ ├── server.rs # 路由、内嵌静态资源、SSE、生命周期 │ ├── listing.rs # 托管目录扫描 │ └── watcher.rs # 文件监听、防抖、快照广播 ├── stash-web/ # React + Vite + TypeScript 控制台 │ ├── package.json # 含 volta 版本固定 │ ├── vite.config.ts # 开发期 /api 代理到 127.0.0.1:8080 │ └── src/ └── public/ # 默认托管目录(可放多个前端项目) ``` `templates/` 与 `assets/` 是上一版 Askama 控制台留下的文件,当前已无任何代码引用, 可以直接删除。 ## 前端怎么被内嵌 1. `npm run build` 产出 `stash-web/dist`; 2. `build.rs` 在编译 Rust 之前把 `dist` 复制到 `$OUT_DIR/web`(先清空,避免旧 hash 文件残留); 3. `src/server.rs` 用 `include_dir!("$OUT_DIR/web")` 在编译期把整棵目录树嵌进二进制; 4. 二进制运行时不再读取任何前端文件。 构建顺序不能颠倒:`dist` 不存在时 `build.rs` 会带着提示信息直接失败,而不是产出一个没有界面的二进制。 `build.rs` 声明了 `rerun-if-changed`,改动 `dist` 后重新 `cargo build` 会自动重新嵌入。 ## 前端开发 ```bash cd stash-web npm install npm run dev # http://127.0.0.1:5173,/api 自动代理到后端 8080 npm run build # 产物输出到 stash-web/dist npm run lint # oxlint ``` 开发时前后端分开跑:一个终端 `cargo run`,另一个终端 `npm run dev`。 控制台的用户资料目前是占位数据(见 `stash-web/src/profile.ts`),后端尚未提供鉴权接口。 ## 命令行参数 | 参数 | 默认值 | 说明 | | --- | --- | --- | | `-r, --root