Skip to content

Repository files navigation

Bun 全栈学校后台管理系统

一个功能精简但覆盖主流全栈技术栈的学校后台管理系统, 用来在一个项目里把 Bun 全栈开发的优势与坑都亲身体会一遍。 后端 Elysia + Drizzle + bun:sqlite,前端 Vue 3 + Vite, 生产态是单进程单端口的「真·Bun 单体」。


1. 技术栈

选型
运行时 / 工具链 Bun (install/run/test/build/fmt 全内置)
后端框架 Elysia (Bun 原生,t schema 类型推导)
HTTP 客户端(前端) @elysiajs/eden (从后端 App 类型生成前端 client,端到端类型安全)
ORM Drizzle ORM
数据库驱动 bun:sqlite (Bun 内置,零原生编译)
密码哈希 Bun.password (内置 bcrypt)
令牌 Web Crypto HMAC-SHA256 (见下方「坑 #1」)
前端 Vue 3 + Vite (SFC + HMR)
校验 后端 Elysia t / 前端 Zod v4
样式 Tailwind CSS v3.4
路由 vue-router
测试 bun test (用 app.handle(Request) 模式,不绑定端口)
部署 bun build --compile 单二进制 + 多阶段 Dockerfile

2. 功能

四个模块均为精简 CRUD,列表统一支持分页 + 关键字搜索 + 关联筛选:

  • 班级 Classes:年级 + 班级名
  • 教师 Teachers:姓名 + 学科 + 职称 + 电话
  • 学生 Students:姓名 + 性别 + 出生日期 + 所属班级(1:N)
  • 课程 Courses:名称 + 授课教师(1:N)+ 上课班级(1:N)+ 课时

外加:管理员登录(JWT)、仪表盘(各实体计数)。


3. 快速开始

3.1 开发态(前端 Vite HMR + 后端 bun --hot

bun install
bun run migrate     # 建表(首次)
bun run seed        # 注入 admin 账号(首次)
bun run dev         # 同时起 Bun :3000 与 Vite :5173

打开 http://localhost:5173 ,登录:

  • 用户名:admin
  • 密码:admin123

开发态前端走 Vite :5173/api 由 Vite 代理到 Bun :3000

3.2 生产态(单端口单体)

bun install
bun run build       # vite build 生成 dist/ + bun build --compile 生成单二进制 ./server
./server            # Windows 下为 server.exe;监听 $PORT(默认 3000)

浏览器直接访问 http://localhost:3000 —— 同一端口同时托管前端 SPA 与 /api启动即自动建表并注入 admin 账号ensureAdmin() 幂等),无需手动 migrate/seed

3.3 Docker

docker build -t bun-school-admin .
docker run -p 3000:3000 -v school-data:/app bun-school-admin

镜像内 CMD ["./server"] 自举数据库;SQLite 文件落在 /app,挂卷即可持久化。


4. 常用脚本

脚本 说明
bun run dev 前后端同时热重载(concurrently)
bun run build:web 仅前端 Vite 构建
bun run build 前端构建 + 后端单二进制编译
bun run migrate 执行建表(幂等 CREATE TABLE IF NOT EXISTS
bun run seed 注入 admin 账号
bun run start 直接跑 src/server/index.ts
bun test 后端测试(10 个用例)

5. 项目结构

bun-school-admin/
├── package.json / tsconfig.json / bunfig.toml
├── vite.config.ts          # root=src/web, outDir=../dist, proxy /api
├── drizzle.config.ts
├── Dockerfile / .dockerignore
├── src/
│   ├── server/
│   │   ├── index.ts        # 入口:ensureAdmin() + app.listen()
│   │   ├── app.ts          # 组装 Elysia 实例(导出 App 类型供 Eden)
│   │   ├── plugins/auth.ts # withAuth():derive+onBeforeHandle 鉴权
│   │   ├── routes/         # auth / dashboard / classes / teachers / students / courses
│   │   ├── db/             # index(bun:sqlite+drizzle) / schema / migrate(raw SQL) / seed
│   │   └── lib/            # password(Bun.password) / jwt(Web Crypto) / crud(通用 CRUD 工厂)
│   ├── shared/             # types.ts(DTO) / zod.ts(表单校验)
│   └── web/                # Vue 前端(views / components / composables / router)
├── dist/                   # 前端构建产物(被 server 静态托管)
└── tests/api.test.ts       # 10 个后端用例

6. 端到端类型安全

  • 后端 app.ts 导出 App 类型;前端 src/web/api/client.tsedenTreaty<App>(base) 生成 client,改接口前端编译期即报错
  • 校验分层:后端 HTTP 入参用 Elysia t(保 Eden 联动); 前端表单用 shared/zod.ts 的 Zod 做校验(与后端结构保持一致)。

7. Bun 全栈「实测优劣清单」(重点)

以下条目均为本项目真实踩到的,不是照搬文档。

✅ 优势(已验证)

  1. 单一工具链bun install/run/test/build 全内置,无需拼 node/npm/tsc/jest/vite。
  2. 原生 TypeScript:后端 .ts 直接跑,零编译配置。
  3. 零原生依赖的后端能力Bun.password(哈希)、bun:sqlite(DB) 全是内置, 彻底避开 better-sqlite3 / bcrypt 的原生编译坑——Bun 最硬的卖点。
  4. 端到端类型安全:Elysia + Eden 让 Vue 拿到后端 HTTP 类型。
  5. 关系型 CRUD 很顺:Drizzle + bun:sqlite 让 1:N 关联、分页、计数类型化且简洁。
  6. 极简部署bun build --compile 一个二进制 + 单 Dockerfile 单端口。
  7. :安装 / 冷启动 / 运行时均显著快于 Node 同构方案。

❌ 代价 / 坑(本项目真实撞上)

  1. Bun.jwt 在本版本是 undefined(实测 Bun 1.3.14)。 import { jwt } from "bun"jwtundefined,直接调用会崩。 → 已改用 Web Crypto 的 HMAC-SHA256 手写 JWTsrc/server/lib/jwt.ts)。 若升级 Bun 后 Bun.jwt 可用,可平滑换回。
  2. 前端 SFC 不能 bun build:Bun 打包器无插件系统,Vue SFC 必须 Vite 打包。 → 「真·Bun 单体」只在运行态成立;开发/构建期前端仍走 Vite。纯 bun build 需放弃 SFC 或换 React。
  3. Elysia 1.4 的「仅含 hook 的插件」经 .use() 挂载时不执行 hook: 一开始把鉴权写成 export const auth = new Elysia().onBeforeHandle(...).use(auth), 结果发现子路由的鉴权根本不触发。 → 改为 export function withAuth(): Elysia {...},在每个路由的同一实例上链式调用 (crudRoutes 返回 withAuth().get(...),dashboard 也 withAuth().get(...))。
  4. 迁移没用 drizzle-kit:演示项目直接 ensureSchema()CREATE TABLE IF NOT EXISTS 原始 SQL(src/server/db/migrate.ts), 避免引入迁移文件依赖,seed 也更简单。正式项目可换 drizzle-kit。
  5. 受限环境下 Vite 的 emptyOutDir 会失败:Vite 的 prepare-out-dirfs.rmSync 路由到「安全删除→回收站」,在部分环境(如本机被拦截)会直接让构建报错。 → 已在 vite.config.tsemptyOutDir: false,改由 build 脚本用 rm -rf dist 预清理。
  6. bun:sqlite 仅本地文件:演示够用;上远程 DB 需换 Postgres + postgres 驱动。
  7. 调试/可观测生态弱于 Node:断点、APM、devtools 插件丰富度不及 Node 生态。
  8. 版本迭代快:Bun 偶有破坏性变更(如 Bun.jwt 的可用性),锁版本 + 关注 changelog 必要。

8. 验证状态

  • bun test10/10 通过(auth 401/200、鉴权中间件、classes CRUD、courses/students 关联查询)。
  • bun run build:web:Vite 构建成功(dist/index.html + assets)。
  • bun build --compile:产出单二进制 server(Windows 为 server.exe,约 99MB,内嵌 Bun 运行时)。
  • 编译后二进制端到端实测:启动即建表 + 注入 admin;/health 正常;登录返回 JWT; 带 token 访问 /api/dashboard 返回计数、无 token 返回 401POST /api/classes 正常; SPA / 返回 200(同端口托管前端)。

9. 后续可扩展(不在本期)

  • 角色细分(admin / teacher 只读自己课程)
  • 学生↔课程 M:N 选课 + 成绩管理
  • 列表导出 Excel / 批量导入
  • SQLite 换 Postgres,对比 ORM 配置差异

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages