路由
路由由文件系统决定。src/pages 中的一个文件就是一个页面,一个目录就是一段 URL,
少数特殊名称用来定义布局、动态参数和错误页面。
文件名
| 文件 | URL |
|---|---|
src/pages/index.ts |
/ |
src/pages/about.ts |
/about |
src/pages/blog/index.ts |
/blog |
src/pages/blog/[slug].ts |
/blog/:slug |
src/pages/blog/[...rest].ts |
/blog/* |
src/pages/api/likes/[slug].server.ts |
/api/likes/:slug |
index对应目录路径:blog/index.ts是/blog,不是/blog/index。[name]匹配一段路径,通过params.name读取。[...rest]匹配路径的剩余部分,包括剩余的多段路径。参数名是数字,模式中第一个通配参数是params[0]。- 页面模块可以是
.js、.mjs、.cjs、.ts、.mts或.cts。 - 名称以
_或.开头的文件和目录不是页面,用来放_layout.ts、_error.ts等特殊文件, 或者被页面导入的模块。测试文件(*.test.*、*.spec.*)和类型声明文件也会被忽略。 - 服务端同时接受
/about和/about/。客户端导航会移除 URL 末尾的/,不重新渲染。
布局
目录中可以包含 _layout.ts。默认导出是用 @layout 标记的 Gem 元素,在子路由的位置渲染
<gemkit-outlet>:
// src/pages/blog/_layout.ts
@layout()
export default class BlogLayout extends GemElement {
@template()
#content = () =>
html`
<aside>Blog</aside>
<section><gemkit-outlet></gemkit-outlet></section>
`;
}布局可以嵌套。src/pages/_layout.ts 是根布局,src/pages/blog/_layout.ts 包裹 /blog 下的内容。
布局本身不是路由,没有 URL。
在共享同一个布局的页面之间导航时,布局元素会被保留,只有子 outlet 改变,
所以布局中的滚动位置、展开的菜单等状态不会丢失。见
错误页面
src/pages/_error.ts 是错误页面,也是没有匹配的路径的 404 页面:
// src/pages/_error.ts
import type { ErrorData } from '@mantou/gemkit';
@page<{}, ErrorData>({ title: ({ data }) => `Error ${data.status}` })
export default class ErrorPage extends GemElement {
@property data?: ErrorData;
@template()
#content = () => html`<h1>${this.data?.status}</h1><p>${this.data?.message}</p>`;
}它没有 URL 模式,也没有服务端模块。它渲染在出错的页面或者布局的位置,请求保留原来的 URL:
load或者actions出错时,它渲染在出错路由的位置,外层布局保留- 没有匹配的路径时渲染为 404 页面
- 意外错误的状态码是
500,生产环境中的信息是Internal Error
error()、notFound() 和 handleError 见
路由优先级
多个路由匹配同一个路径时,更具体的路由优先。每个布局中的路由按段排序:
- 静态段
- 动态段(
:name) - 缺少的段,所以
/在/*之前 - 通配段(
*)
例如 /blog/new 优先于 /blog/[slug],/blog 优先于 /blog/[...rest]。
页面模块和服务端模块
页面模块和同名的 *.server.ts 是一对,文件名和路由都相同:
src/pages/blog/[slug].ts
src/pages/blog/[slug].server.ts服务端模块只在服务端加载,客户端代码导入它会导致构建失败。
没有同名页面模块的 *.server.ts 是
应用文件
除了 pages 和 locales,这些可选文件用来配置应用:
| 文件 | 用途 |
|---|---|
src/app.ts |
在路由之前导入,用来设置全局样式、store 等。 |
src/app.server.ts |
服务端请求的 handle 和 handleError。 |
src/index.html |
替换默认的 HTML 模板,需要保留 <!--gemkit-body-->。 |
src/elements/*.ts |
根据 app-* 标签自动导入的元素(见下文)。 |
src/elements 中的元素可以直接在模板中使用,不需要导入。src/elements/counter.ts 就是
app-counter 元素,可以使用 gem.autoImport
语言
语言前缀不属于页面目录树。有 src/locales 时,上面的每个路径也会出现在 /{lang} 下,
例如 /zh/about。默认语言默认没有前缀,见
