- 后端
- 前端
【免费下载链接】blitz
⚡️ The Missing Fullstack Toolkit for Next.js
这篇技术指南以 Blitz.js 官方脚手架生成的新应用模板(仓库中的 packages/generator/templates/app)为讲解对象,面向使用blitz new创建 Next.js 全栈应用的开发者。读完本文,你将掌握模板的启动流程、环境变量配置、CLI 命令体系、目录结构规划,以及模板内置的"注册 / 登录 / 找回密码"认证体系与 Prisma 数据层的源码级实现细节,能够在此基础上快速扩展自己的业务模型。
一、模板是什么:Blitz.js 脚手架的默认产物
Blitz.js(项目名 blitz,仓库见 README.md)是面向 Next.js 的"全栈工具包"。当你执行blitz new创建一个新项目时,生成器会把 templates/app 这套模板复制到目标目录,并把模板文件名中的__name__占位符替换为你的应用名。
这套模板与另一套经典模板最大的差异在于:它默认采用 Next.jsApp Router(src/app目录)结构,而不是旧版的pages目录结构。从 app-generator.ts 可以看到,生成器在template.path === "app"时会把认证相关的组件与 mutation 统一移动到(auth)路由组下,这是 App Router 特有的组织方式。
模板自带的package.json(即 package.ts.json)锁定了一套完整的技术栈:blitz+@blitzjs/auth+@blitzjs/next+@blitzjs/rpc+next15 +react19 +prisma+zod+formik,并默认开启 Prisma 与一套"开箱即用"的邮箱密码认证。
二、快速开始:安装 CLI 并创建应用
模板 README 指出,Blitz 自带一个强大的 CLI,全局安装即可使用:
npm i -g blitz安装后,创建应用:
blitz new my-app生成器源码位于 packages/generator/src/generators/app-generator.ts,它会询问 TypeScript / JavaScript、表单库(final-form / formik / react-hook-form,对应 templates/app/_forms 下的三个实现)等选项,然后渲染模板。
三、启动开发服务器
模板 README 给出的第一个操作是:
blitz dev随后用浏览器打开 http://localhost:3000 即可看到应用首页。首页代码位于 src/app/page.tsx,它是一个异步 Server Component:通过invoke(getCurrentUser, null)直接调用服务端查询,如果当前没有登录用户就展示Sign Up / Login按钮,否则展示用户 id、角色与登出按钮——也就是说,模板生成的应用天然自带完整的注册登录闭环。
首页还提示了一条后续开发主线:在终端依次执行blitz generate all project、Ctrl + c、blitz dev,即可为Project模型生成查询、变更与页面,然后访问/projects验证新生成的 CRUD 页面。
四、环境变量配置
Blitz 遵循 dotenv 惯例读取环境变量。模板要求准备两个文件:
.env.local(开发/生产本地环境)
DATABASE_URL=postgresql://<YOUR_DB_USERNAME>@localhost:5432/__name__.env.test.local(测试环境)
DATABASE_URL=postgresql://<YOUR_DB_USERNAME>@localhost:5432/__name___test注意这里的__name__是模板占位符,创建应用后会被替换为你的数据库名。测试库通常与开发库分开命名(后缀_test),避免测试数据污染。
环境变量被 db/schema.prisma 引用:
datasource db { provider = "sqlite" url = env("DATABASE_URL") }模板默认的 provider 是sqlite,也就是说即使不配置 Postgres,直接使用DATABASE_URL=file:./dev.db之类的 SQLite 连接串也能跑通开发(模板 db/dev.db 即是预置的开发库)。要切换到 PostgreSQL,把 provider 改为postgresql并配置对应的连接串即可,同时注意 schema.prisma 中的注释提示:枚举类型(如 TokenType)仅在 Postgres 下可用。
另外,模板的 gitignore 明确忽略了.env*.local,保证密钥类环境变量不会进入版本控制。
五、运行测试
模板 README 给出了测试命令:
yarn test模板配套了基于Vitest与react-testing-library的测试环境。查看模板 package.ts.json 的 scripts 可以看到实际命令是:
"test": "vitest run --passWithNoTests", "test:watch": "vitest"模板已经内置了两个真实的单元测试示例,直接展示了如何测试认证 mutation:
- forgotPassword.test.ts:用
vi.mock固定generateToken返回值、mockpreview-email,验证"用户不存在时不抛错"以及"创建新 token、删除旧 token、发送邮件"的完整流程; - resetPassword.test.ts:构造"过期 token / 有效 token / 不存在 token"三种场景,验证无效 token 抛错、有效 token 被删除、密码被更新且可以用
SecurePassword.verify验证。
这两个测试文件在生成应用后会被保留,是编写后续业务测试的绝佳参照。
六、Blitz CLI 命令总览
模板 README 列出了 CLI 的全部子命令。下表在原文基础上补充了每个命令的用途说明:
| 命令 | 用途 |
|---|---|
blitz dev | 启动开发服务器(热更新) |
blitz build | 创建生产构建 |
blitz start | 启动生产服务器(需先 build) |
blitz export | 把应用导出为静态站点 |
blitz prisma | 运行 Prisma 相关命令(如blitz prisma migrate dev) |
blitz generate | 为项目生成新文件(模型、页面、查询、变更等) |
blitz console | 运行 Blitz 控制台 REPL,可交互式调用查询与变更 |
blitz install | 安装 recipe(社区维护的预置功能包) |
blitz help | 显示帮助 |
blitz test | 运行项目测试 |
从源码结构看,这些命令分别实现在 packages/blitz/src/cli/commands 下:new.ts(创建应用)、generate.ts(生成文件)、console.ts(REPL)、prisma.ts与db.ts(数据库)、codegen.ts(类型代码生成)、routes.ts(路由工具)以及next/子目录(dev/build/start 等 Next.js 相关命令),统一由 cli/index.ts 组装分发。
七、项目目录结构逐层解读
模板 README 给出了生成后的完整目录树。结合仓库中真实模板,将关键目录整理如下(__name__为你的应用名):
__name__ ├── README.md ├── db │ ├── index.ts # Prisma 客户端实例(enhancePrisma 增强) │ └── schema.prisma # 数据模型定义 ├── integrations # 第三方集成(Stripe、Sentry 等)放在这里 ├── mailers │ └── forgotPasswordMailer.ts ├── next-env.d.ts ├── next.config.js # Next.js 配置(withBlitz 包装) ├── package.json ├── public # 静态资源 ├── src │ ├── app # App Router 应用目录 │ │ ├── (auth) # 认证路由组(login/signup/forgot-password/reset-password + mutations + components) │ │ ├── api/rpc/... # Blitz RPC 路由挂载点 │ │ ├── components # Form / LabeledTextField 等通用表单组件 │ │ ├── users # 当前用户查询与 hook │ │ ├── blitz-client.ts / blitz-server.ts / blitz-auth-config.ts │ │ ├── error.tsx / loading.tsx / layout.tsx / page.tsx │ │ └── styles # 全局样式 │ └── pages # 兼容的 Pages Router(仅保留 API RPC 路由时为空) ├── tsconfig.json └── types.ts # Role 类型与 Session PublicData 的全局声明各目录职责如下:
src/:整个项目的主容器,页面与 API 路由都放在这里。App Router 下页面即src/app/**/page.tsx;db/:数据库配置与迁移所在地。db/index.ts 使用enhancePrisma(PrismaClient)创建增强版 Prisma 客户端,并在查询时自动附带ctx.session相关的请求上下文;模型与迁移则看schema.prisma与db/migrations/;public/:存放图片、视频等静态资源;integrations/:存放第三方集成代码,如 Stripe、Sentry 的客户端实例封装;mailers/:邮件发送器。forgotPasswordMailer.ts 展示了模板的做法:开发环境下用preview-email在浏览器预览邮件,生产环境下抛出 "No production email implementation" 错误,提示你接入真实的邮件服务商;package.json:依赖与脚本;tsconfig.json:TypeScript 推荐配置(strict 模式 +@/*路径别名);next.config.js则用 withBlitz 包装,并开启experimental.typedRoutes;types.ts:types.ts 声明了Role = "ADMIN" | "USER",并通过模块扩充把Session.PublicData的类型钉死为{ userId, role },让鉴权逻辑全程类型安全。
表单组件与数据模型
模板在_forms/下提供了 final-form / formik / react-hook-form 三套等价实现。以 final-form 版 Form.tsx 为例,它接收zodschema,用validateZodSchema做校验,把提交错误渲染到role="alert"区域;LabeledTextField.tsx 则封装了字段 label、错误提示与 number 类型解析。
数据层模型在 schema.prisma 中定义:
- User:
id、createdAt、updatedAt、可选name、唯一email、可选hashedPassword、默认"USER"的role,并关联tokens与sessions; - Session:
handle(唯一)、hashedSessionToken、antiCSRFToken、publicData、privateData与可选的user关联——这是 Blitz 会话机制在数据库侧的落点; - Token:
hashedToken、type、expiresAt、sentTo,并以@@unique([hashedToken, type])约束唯一性,用于密码重置等一次性令牌场景。
八、模板内置的认证与 RPC 体系(源码纵深)
这是模板最有价值的部分——一个开箱即用的认证闭环。我们从"两端 + 一路由"看它的装配方式。
服务端装配
src/app/blitz-server.ts 是服务端的核心:
const {api, getBlitzContext, useAuthenticatedBlitzContext, invoke, withBlitzAuth} = setupBlitzServer({ plugins: [ AuthServerPlugin({ ...authConfig, storage: PrismaStorage(db), isAuthorized: simpleRolesIsAuthorized, }), RpcServerPlugin({}), ], logger: BlitzLogger({}), })要点:
AuthServerPlugin使用PrismaStorage(db)把会话持久化到数据库(即上面 schema 中的 Session 模型),simpleRolesIsAuthorized提供基于角色的轻量鉴权;RpcServerPlugin让查询/变更函数变成可跨端调用的 RPC;- 导出的
invoke允许在 Server Component 中直接调用查询/变更,首页正是这样拿到当前用户的。
客户端装配
src/app/blitz-client.ts 通过setupBlitzClient组合AuthClientPlugin(authConfig)与BlitzRpcPlugin({}),导出BlitzProvider,由 layout.tsx 包裹全局;认证配置在 blitz-auth-config.ts,目前只有cookiePrefix: "app-dir",用于给会话 Cookie 加前缀,避免多应用冲突。
RPC 路由挂载
src/app/api/rpc/blitzrpcroute/route.ts 是 App Router 下 RPC 的唯一入口:
export const {GET, HEAD, POST} = withBlitzAuth(rpcAppHandler())rpcAppHandler()处理全部查询/变更的 HTTP 调用,withBlitzAuth负责注入认证上下文。
认证流程逐个拆解
模板的认证 mutation 全部位于 src/app/auth/mutations:
- 注册 signup.ts:
SecurePassword.hash哈希密码,db.user.create建用户,再blitzContext.session.$create({userId, role: "user"})直接建立会话——注册即登录; - 登录 login.ts:
Login.parse做 zod 校验,SecurePassword.verify验密;若返回VALID_NEEDS_REHASH,说明哈希强度可升级,自动用新哈希更新数据库(安全加固细节);校验失败统一抛AuthenticationError,避免泄露"用户是否存在"; - 登出 logout.ts:一行
ctx.session.$revoke()吊销当前会话; - 忘记密码 forgotPassword.ts:完整实现"生成 token(
generateToken明文 +hash256落库)→ 删除该用户旧 token → 写入 4 小时过期的RESET_PASSWORDtoken → 发送邮件"的流程;用户不存在时故意setTimeout(750)等待相同时间,防止攻击者通过响应时间探测邮箱是否注册; - 重置密码 resetPassword.ts:按
hash256(token)查找、使用后立即删除 token(防重放)、校验过期时间、更新密码、删除该用户全部会话,最后调用login用新密码重新登录; - 修改密码 changePassword.ts:用
resolver.authorize()强制登录态,先验证当前密码再写新哈希。
所有 mutation 都用resolver.pipe(resolver.zod(Schema), ...)包裹,输入校验由 validations.ts 中的 zod schema 完成——例如密码要求 10~100 位并自动 trim,ResetPassword用refine保证两次密码一致。
当前用户查询与 Hook
- getCurrentUser.ts:
ctx.session.userId为空直接返回 null,否则按 id 查出用户(只 select id/name/email/role); - useCurrentUser.ts:客户端 Hook,用
useQuery包装上述查询,供客户端组件使用。
九、内置开发工具:ESLint、Husky 与 Prettier
模板 README 强调,Blitz 自带一组"纠正与格式化代码"的工具,且可修改、可卸载:
- ESLint:检查坏实践并提示。可通过
.eslintrc.js自定义,内置blitz的 eslint 配置(见仓库根目录 packages/config/eslint.js 的配置包),也可安全移除; - Husky:注入 Git hooks,例如
pre-commit在每次提交前执行。hooks 存放在.husky/;提交/推送遇到问题时参照 Husky 官方 troubleshooting 排查; - Prettier:统一代码风格。通过
.prettierrc配置,.prettierignore指定忽略文件。模板在 package.ts.json 中预置了semi: false、printWidth: 100风格,并用lint-staged在提交前对*.{js,ts,tsx}自动eslint --fix。
此外,模板还带一个 npmrc,通过public-hoist-pattern提升@tanstack/react-query、next、secure-password等关键依赖的安装层级,注释明确写着"Needed for Blitz to work properly. Don't remove the lines above"——如果安装后运行时出现依赖解析问题,先检查这个文件是否被改动。
十、基于模板快速扩展业务
模板 README 给出了一套最小可用的扩展工作流:
# 1. 为 Project 模型生成全套文件(模型、查询、变更、页面) blitz generate all project # 2. 停止开发服务器 # Ctrl + c # 3. 重新启动 blitz dev # 4. 浏览器访问生成的 CRUD 页面 # http://localhost:3000/projectsblitz generate的实现位于 packages/generator,它支持从schema.prisma读取模型并按需生成 query / mutation / page / route 等文件。每生成一个新模型,都可以沿用模板已有的安全模式:用resolver.pipe(resolver.zod(Input), resolver.authorize(), handler)包裹变更,用 zod 校验输入,用SecurePassword处理密码类敏感数据。
结语
从blitz new到一套带认证、带数据库、带测试的全栈应用,模板把 Blitz.js 的最佳实践浓缩在一个可复制的目录结构中。理解这份模板的装配方式——setupBlitzServer/setupBlitzClient的插件机制、PrismaStorage的会话落库、RPC 路由与invoke调用链、以及一整套密码学安全的认证 mutation——就等于掌握了 Blitz.js 的核心运行原理。后续无论是接入 Postgres、接入真实邮件服务,还是生成新的业务模型,都可以在这份模板的基础上平滑演进。
- 后端
- 前端
【免费下载链接】blitz
⚡️ The Missing Fullstack Toolkit for Next.js
相关推荐
Blitz.js Passport.js 认证示例应用:从配置到 OAuth 登录的完整实战指南
Blitz.js Passport.js 认证示例应用:从配置到 OAuth 登录的完整实战指南 导读 apps/toolkit app passportjs/
后端前端NIST AI RMF 合规实战:817 个安全技能的 AI 风险映射
NIST AI RMF 合规实战:817 个安全技能的 AI 风险映射 审计方递来一份清单:请逐条说明你的 AI 系统对应 NIST AI RMF 哪些子类别,
网络安全AI 技能/插件渗透测试红蓝对抗Microsoft.Orleans.Templates 项目模板使用指南:从 `dotnet new orleans` 到完整集群应用
Microsoft.Orleans.Templates 项目模板使用指南:从 dotnet new orleans 到完整集群应用 导读 本文围绕仓库 temp
后端微服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考