Astro 高级路由实战:用 src/fetch.ts 与 Hono 中间件接管请求管线
本文以 Astro 官方示例 examples/advanced-routing 为主体,完整还原其项目结构、配置与命令,并逐行剖析 src/fetch.ts 中基于 Hono 的请求管线——从请求日志、认证拦截、Astro Actions 到页面渲染与 i18n 后处理。读完后,你将掌握如何在 Astro 7 中用 Hono 中间件自定义路由行为(鉴权重定向、重定向、多语言路由),并理解底层 fetchFile 入口与 astro/hono API 的对应关系。
快速开始
该示例可作为 create-astro 的官方模板直接使用:
npm create astro@latest -- --template advanced-routing
示例演示了 Astro 的实验性高级路由能力:通过 src/fetch.ts(旧称 src/app.ts)入口,用 Hono 风格的中间件接管整个请求管线,实现认证拦截、重定向和多语言(locale)页面路由。
运行前提(依据 package.json):
- Node.js
>=22.12.0 - 核心依赖:
astro(^7.2.10)、hono(^4.12.14)、@astrojs/node(^11.1.5)
项目结构
示例工程目录如下(来自 README 并对照仓库实际文件):
/
├── src/
│ ├── actions/ # Astro Actions(RPC + 表单)
│ ├── layouts/ # 布局组件 Layout.astro
│ ├── pages/ # 路由页面
│ │ ├── dashboard/ # 受保护的仪表板
│ │ └── es/ # 西班牙语页面
│ ├── fetch.ts # 请求管线入口(Hono app)
│ └── ...
├── astro.config.mjs
├── package.json
└── tsconfig.json
Astro 会在 src/pages/ 目录下寻找 .astro 或 .md 文件,每个文件按其文件名暴露为一个路由。本示例包含的页面有:
- src/pages/index.astro:英文首页
- src/pages/es/index.astro:西班牙语页面
- src/pages/dashboard/index.astro:需要登录的仪表板
- src/pages/login.astro:登录页
- src/pages/old-dashboard.astro:用于演示重定向的旧路径页面
- src/pages/404.astro:自定义 404 页
真正决定请求如何流动的是 src/fetch.ts 文件——它接管了请求管线,组合 Astro 内置中间件与自定义 Hono 中间件,处理认证、重定向和 locale 路由等行为。
服务端渲染(SSR)配置
该示例启用 SSR,配置文件为 astro.config.mjs:
// @ts-check
import node from '@astrojs/node';
import { defineConfig } from 'astro/config';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
i18n: {
defaultLocale: 'en',
locales: ['en', 'es'],
},
});
各配置项的作用:
| 配置项 | 取值 | 说明 |
|---|---|---|
output |
'server' |
全站点采用服务端渲染,页面在请求到达时实时生成 |
adapter |
node({ mode: 'standalone' }) |
使用 @astrojs/node 适配器,产物为独立 Node 进程部署形态 |
i18n.defaultLocale |
'en' |
默认语言为英文 |
i18n.locales |
['en', 'es'] |
声明支持的语言,高级路由据此生成 locale 重定向与回退 |
高级路由与 fetchFile 入口的关系可以在 Astro 的类型定义中找到直接依据。在 config.ts 中,fetchFile 选项的文档明确写道:默认值为 'fetch',即 Astro 会查找 src/fetch.ts(也接受 .js / .mjs / .mts);该文件“允许你用 Web Fetch 标准或自己的 Hono 中间件来组合 Astro 的请求管线”。若你已把 src/fetch.ts 用于其他用途,可以改名为其他文件(如 fetchFile: 'handler'),或设为 null 禁用该入口。
src/fetch.ts:请求管线全解析
示例的核心文件是 src/fetch.ts。它默认导出一个 Hono app,中间件的注册顺序即请求的处理顺序:
import { getCookie } from 'hono/cookie';
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { actions, middleware, pages, i18n } from 'astro/hono';
const app = new Hono();
// 请求日志 —— 在终端看到每一个请求
app.use(logger());
// 认证门禁 —— 在 Astro 渲染之前拦截未登录的 dashboard 请求
app.use(async (c, next) => {
const url = new URL(c.req.url);
if (url.pathname.startsWith('/dashboard')) {
const session = getCookie(c, 'session');
if (!session) {
return c.redirect('/login');
}
}
return next();
});
// Astro Actions(RPC + 表单)
app.use(actions());
// 来自 src/middleware.ts 的用户中间件(内部会调用下一个 Hono handler)
app.use(middleware());
// 页面渲染(端点、页面、回退页)
app.use(pages());
// i18n 后处理(locale 重定向、回退路由)
app.use(i18n());
export default app;
逐层解读:
app.use(logger()):Hono 内置的请求日志中间件,每个请求都会打印到终端,便于调试管线顺序。- 认证门禁(自定义中间件):这是高级路由最典型的用例——在 Astro 渲染页面之前就能基于 Cookie(此处读取
session)做鉴权。当请求路径以/dashboard开头且没有sessionCookie 时,直接c.redirect('/login'),请求根本不会进入页面渲染阶段。这种“渲染前拦截”是传统的astro:config中间件无法灵活表达的模式。 actions()(来自astro/hono):挂载 Astro Actions,提供类型安全的 RPC 与表单提交处理,对应示例中的 src/actions/index.ts。middleware()(来自astro/hono):桥接 Astro 传统的用户中间件,内部会调用下一个 Hono handler,使旧式中间件与新管线共存。pages():页面渲染中间件,负责端点(endpoint)、页面与回退(404)的最终渲染,是管线的“收口”环节。i18n():i18n 后处理,负责 locale 重定向与回退路由,与配置中的i18n.locales: ['en', 'es']配合,把根路径按用户语言导向src/pages/下对应的/es/...页面。
关于 astro/hono 这个虚拟入口,源码中有明确注释:在 fetch-state.ts 中,负责管线状态的核心类被标注为“This class is user-facing via astro/fetch and astro/hono”,印证了 astro/hono 是官方对用户暴露的 Hono 集成入口。
运行命令
所有命令均在项目根目录、终端中执行(继承自 README 的命令表):
| 命令 | 作用 |
|---|---|
npm install |
安装依赖 |
npm run dev |
启动本地开发服务器,默认 localhost:4321 |
npm run build |
构建生产站点到 ./dist/ |
npm run preview |
在部署前本地预览构建产物 |
npm run astro ... |
运行 CLI 命令,如 astro add、astro check |
npm run astro -- --help |
查看 Astro CLI 帮助 |
要点小结
- 高级路由的本质是用
src/fetch.ts导出的 Hono app 替换默认请求管线,中间件顺序即处理顺序; - 认证、重定向等“渲染前”逻辑应放在
pages()之前,locale 归一化等“后处理”逻辑放在其后; astro/hono提供的actions、middleware、pages、i18n四个 API 分别对应 Actions、传统中间件桥接、页面渲染与 i18n,可按需组合;- 该能力当前在配置语义上仍被官方文档定位为实验特性(README 中即写作 experimental advanced routing),生产使用建议先验证
fetchFile、astro/hono的稳定版本行为。
如需继续深入,可查看配置文件类型定义 packages/astro/src/types/public/config.ts、管线状态实现 packages/astro/src/core/fetch/fetch-state.ts,以及本示例的全部页面源码 examples/advanced-routing/src/pages。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00