Ghost 主题路由配置完全指南:读懂与使用routes.yaml(content/settings)
【免费下载链接】GhostIndependent technology for modern publishing, memberships, subscriptions and newsletters.项目地址: https://gitcode.com/GitHub_Trending/gh/Ghost
导读
routes.yaml是 Ghost 博客平台中决定站点 URL 结构与路由映射的核心配置文件,它决定了首页聚合哪些文章、每篇文章使用什么链接格式、标签与作者归档页挂在哪个路径之下。本文以 Ghost 仓库中 ghost/core/content/settings/README.md 为主体,结合其源码级实现(路由设置解析器、存储适配器与动态路由服务),为你完整拆解默认配置文件的三个组成块(routes、collections、taxonomies),讲清楚每个键的含义、可扩展的进阶选项,以及如何安全地修改并让改动生效。
配置文件在哪:content/settings/routes.yaml
在标准的 Ghost 安装目录中,路由设置文件位于content/settings/routes.yaml。仓库中对应的存放位置与说明文档为 ghost/core/content/settings/README.md,其当前仅收录了一个README.md,因为真正生效的routes.yaml属于运行期数据——首次发布内容时才会由系统生成到本地磁盘。
从源码看,文件读写由文件型存储适配器完成:FileStore.ts 中以常量YAML_FILENAME = 'routes.yaml'定义了文件名,并指向content/settings目录作为basePath。它会在文件不存在时自动回落读取打包的内置默认值 default-routes.yaml,这意味着即使你从未手工创建过routes.yaml,Ghost 也会用内置默认路由启动,真正的文件只在第一次保存修改后才落地磁盘。
Ghost 还支持把routes.yaml托管到 S3 之类的远程存储(见 S3RouteSettingsStore.ts),实现多实例间共享同一份路由配置。
默认配置逐段精读
README 中展示的默认routes.yaml全文如下(与仓库内置默认 default-routes.yaml 完全一致):
routes: collections: /: permalink: '/{slug}/' template: - index taxonomies: tag: /tag/{slug}/ author: /author/{slug}/顶层结构:三段式(routes / collections / taxonomies)
文件由三个顶层键构成,缺一不可但都允许留空。这一结构在解析层被定义为固定的三段式 schema(见 route-settings-parser.ts):
const RouteSettingsSchema = z.object({ routes: z.record(z.string(), z.unknown()).nullable().optional().default({}), collections: z.record(z.string(), z.unknown()).nullable().optional().default({}), taxonomies: z.record(z.string(), z.string()).nullable().optional().default({}), });| 顶层键 | 用途 | 默认配置中的内容 |
|---|---|---|
routes | 自定义静态路由(如/about/独立页面、RSS 等附加路由),可挂载模板或 channel 控制器 | 空 |
collections | 内容聚合路由,决定某路径下展示哪些文章及其 permalink 格式 | 根路径/,permalink 为/{slug}/,模板index |
taxonomies | 分类归档路由,为 tag 与 author 定义 URL 模式 | /tag/{slug}/与/author/{slug}/ |
collections:文章的聚合与 URL 生成器
collections 是配置中信息量最大的部分。默认配置只保留一个根集合/,它会聚合站点全部文章,并让每一篇公开发布的文章获得https://你的域名/{slug}/这样的永久链接。
各字段含义如下:
/(collection 路径):作为顶层键的 key,表示这个集合挂在站点的哪个 URL 前缀下,必须以/开头和结尾。permalink:集合内文章生成 URL 的模板。{slug}是动态占位符,在渲染时被替换为文章 slug。因此permalink: '/{slug}/'意味着文章“hello-world”的最终链接为/hello-world/。template:渲染该集合列表页使用的主题模板名。默认值为index,即主题的index.hbs。它接受单个字符串或字符串数组,数组用于按顺序做模板回退(见 route-settings-parser.ts 中TemplateField的归一化逻辑)。
taxonomies:标签与作者的归档 URL
taxonomies定义 Ghost 的两类分类归档——tag(标签)与author(作者)。在解析器中,任何非tag/author的键都会被直接判为非法(见 route-settings-parser.ts):
if (!['tag', 'author'].includes(key)) { throw validationError(..., 'Unknown taxonomy. Please use tag or author.', ...); }注意这里使用的是{slug}占位符写法,与 permalink 的约束一致。源码对路径合法性有统一校验(validatePath),几条硬性规则是:
- 必须以
/开头、以/结尾; - 只能使用
{param}占位符语法,不能用 Express 风格的:param——若写成/tag/:slug/,解析器会报错并提示改为/tag/{slug}/。
进阶:让routes.yaml支撑更多站点形态
默认配置是最小可用集合。源码解析器(route-settings-parser.ts)实际支持的字段远不止 README 展示的这些,下面是经过源码验证的完整能力矩阵。
routes区块:静态页面与 channel
routes下的每条记录把一个 URL 路径映射到一个模板或一个带controller: channel的列表控制器。合法的 route 值有两种形态:
- 简写形态——直接写模板名:
routes: /about/: template: about- channel 形态——把路径变成一个可筛选的文章流(路由对象 schema 见 route-settings-parser.ts):
routes: /featured/: controller: channel template: - featured filter: 'featured:true' order: published_at desc limit: 10 rss: true此时支持controller: channel、template、filter、order、limit、rss及data等可选键。默认的routes:之所以留空,是因为 Ghost 的主题层(如/featured/、分页 URL)由路由控制器的默认机制补全。
collections的可选键
collection 除了permalink与template,还可叠加以下过滤与排序能力(collection schema 见 route-settings-parser.ts):
| 键 | 类型 | 作用 | 示例 |
|---|---|---|---|
filter | string | NQL 过滤器,决定哪些文章进入该集合 | filter: 'tag:photo' |
order | string | 排序表达式 | order: published_at desc |
limit | number /'all' | 每页条数上限 | limit: 5 |
rss | boolean | 是否为此集合开启 RSS | rss: true |
data | 见下文 | 为集合页面注入额外数据 | data: tag.recipes |
例如,用filter实现“仅聚合某一标签文章”的独立博客集合:
collections: /blog/: permalink: /blog/{slug}/ template: blog filter: 'tag:blog'data:路由级数据注入与两个保留命名空间
data可以把一个具名资源直接“喂”给特定模板(比如在首页渲染“特色标签”)。它支持两种写法,底层模型见 base.ts:
简写形态resource.slug,资源必须是tag、page、post、author:
collections: /: permalink: /{slug}/ template: index data: featured_post: post.hello-world recipes_tag: tag.recipes其中recipes_tag这样自定义的 key 会暴露给模板使用。但解析器保留了若干禁止用作自定义 key 的名字(RESERVED_DATA_KEYS,见 route-settings-parser.ts):resource、type、limit、order、include、filter、status、visibility、slug、redirect;另外author因历史原因也被单独保留并建议更换名字。
长格式——用 map 描述一个具名数据条目,需声明type与resource:
routes: /resources/tag/recipes/: template: tag-recipes data: tag: type: read resource: tags slug: recipestype只能取read(读取单条,需配slug)或browse(按filter/limit等批量读取,见 route-settings-parser.ts)。长格式下resource使用复数集合名:tags、posts、pages、authors。
修改配置的正确姿势:三种生效途径
途径一:直接编辑文件后重启
在content/settings/routes.yaml中改好后重启 Ghost。每次启动时,动态路由服务会把路由设置载入前端 RouterManager(见 dynamic-routing-service.js 的start()流程,它由 boot.js 中的initDynamicRouting在每次启动时调用)。
途径二:通过管理后台下载 / 上传
在 Ghost Admin 的Settings → Advanced → Routes中可直接编辑并保存routes.yaml。上传链路(dynamic-routing-service.js)的执行顺序是:
- 解析并校验上传内容——非法文件在落盘前就被拒绝(
ROUTE_SETTINGS_VALIDATION_ERROR); - 通过
store.replace()原子写盘,旧文件自动生成带时间戳的备份(见 FileStore.ts); - 触发
bridge.reloadFrontend(),前端路由热重载,无需重启进程。
途径三:API 接口
Admin API 暴露了路由设置的下载与上传端点(入口见 settings.js),便于自动化部署流程把routes.yaml作为代码资产管理。
校验规则与常见报错
配置文件解析使用 js-yaml 读取 YAML,再用 zod schema 校验(route-settings-parser.ts)。较常见的错误及原因:
Missing leading slash/Missing trailing slash:所有路径(route 路径、collection 路径、permalink、taxonomy permalink)必须以/开头并结尾。uses the :param notation:路径中混入了 Express 风格:slug,应改写为 Ghost 的{slug}。Unknown taxonomy:taxonomies 区块只允许tag和author。Please define a permalink route:collection 缺少permalink(见校验 route-settings-parser.ts)。Please define a template:某个 route 既没写模板、又没有data/content_type兜底。"author" is reserved:data区块用author作自定义键。
当routes.yaml非法且无法加载时,Ghost 会记录一条明确的ROUTE_SETTINGS_VALIDATION_ERROR日志并向上抛出真实错误,提示你修复文件(dynamic-routing-service.js),而不是默默降级运行。
路由系统全貌:配置文件如何变成站点 URL
routes.yaml只是起点,配置解析后的路由模型(Route/CollectionConfig/TaxonomyConfig,定义见 base.ts)会被前端路由系统消费,链路分布在以下模块中:
- 路由模型与存储抽象:route-settings-base 包定义了
RouteSettingsStoreBase及get()/replace()接口,是本地磁盘(FileStore.ts)与 S3(S3RouteSettingsStore.ts)两种实现的共同契约。 - 前端路由注册:配置解析产物交给 RouterManager,按类型创建 collection / taxonomy / static 等路由器并挂载到父路由,相关文件见 routing/index.js、router-manager.js。
- URL 服务:后台 URL 服务会基于这些路由构建站点所有内容 URL,即使不对外提供页面服务,后台任务也需要加载路由(见 url/config.js 与 lazy-url-service.ts)。
因此在 Ghost 中,“改 URL 结构”从来不是只影响链接显示,而是牵动整条从路由注册、内容分页到站点地图与 RSS 的链路,而这一切都以routes.yaml为唯一事实来源。
小结
content/settings/routes.yaml是一份“短小但系统级”的配置:三段结构分别治理静态路由、文章聚合与分类归档;占位符一律使用{slug};修改后可经文件重启、Admin 上传热加载或 Admin API 三种方式生效。理解它,就等于掌握了自定义 Ghost 博客 URL 架构的钥匙——无论是想改 permalink 格式、拆出按标签隔离的二级博客,还是为自定义页面注入路由级数据,都可以从这份 YAML 开始,再回到源码中的 schema 校验确认每个字段的合法取值与边界。
【免费下载链接】GhostIndependent technology for modern publishing, memberships, subscriptions and newsletters.项目地址: https://gitcode.com/GitHub_Trending/gh/Ghost
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考