文件系统路由 API
示例
当您想创建动态页面时,例如为您的博客创建单独的博文页面,请使用文件系统路由 API。
您应该能够通过这个基于文件的 API 完成大多数常见任务。如果您想更精细地控制页面创建,则应使用 createPages API。
Gatsby 的 GraphQL 数据层 中的集合可以创建动态页面,并且可以创建 仅客户端路由。
完整的示例,展示了所有选项,可以在 Gatsby 的示例文件夹 中找到。
集合路由
设想一个 Gatsby 项目,它从 product.yaml 文件和多个 Markdown 博文中提取数据。在构建时,Gatsby 会自动 推断 字段,并为这两种类型(Product 和 MarkdownRemark)创建多个 节点。
要创建集合路由,请在文件名中使用花括号({ })来表示动态 URL 段,这些段与节点中的字段相关。这里有一些示例:
src/pages/products/{Product.name}.js将生成一个像/products/burger这样的路由src/pages/products/{Product.fields__sku}.js将生成一个像/products/001923这样的路由src/pages/blog/{MarkdownRemark.parent__(File)__name}.js将生成一个像/blog/learning-gatsby这样的路由
Gatsby 为集合路由中的每个节点创建一个页面。因此,如果您有三个作为博文的 markdown 文件,Gatsby 将从集合路由创建这三个页面。当您添加和删除 markdown 文件时,Gatsby 会相应地添加和删除页面。
集合路由可以为任何 GraphQL 数据类型创建。在 Gatsby 中创建新的集合路由的过程是添加一个源插件,使用 GraphiQL 识别类型和字段来构建路由文件名,然后编写路由组件。
语法(集合路由)
使用集合路由时,有一些通用的语法要求:
- 文件路径的动态段必须以花括号(
{ })开头和结尾。 - 类型是区分大小写的(例如
MarkdownRemark或contentfulMyContentType)。请在 GraphiQL 中检查正确的名称。 - 动态段必须同时包含类型和字段,例如
{Type.field}或{BlogPost.slug}。
嵌套路由
您可以在路径中使用动态段多次。例如,您可能希望将产品名称嵌套在其产品类别中。例如:
src/pages/products/{Product.category}/{Product.name}.js将生成一个像/products/toys/fidget-spinner这样的路由src/pages/products/{Product.category}/{Product.name}/{Product.color}.js将生成一个像/products/toys/fidget-spinner/red这样的路由
字段语法
点表示法
使用 . 来表示您想访问节点上的某个字段。
src/pages/products/{Product.name}.js 将生成以下查询:
下划线表示法
使用 __(双下划线)来表示您想访问节点上的嵌套字段。
src/pages/products/{Product.fields__sku}.js 将生成以下查询:
您可以任意嵌套深度,例如 src/pages/products/{Product.fields__date__createdAt}.js 将生成以下查询:
括号表示法
使用 ( ) 来表示您想访问一个 GraphQL 联合类型。这通常对于 Gatsby 为您创建的类型是可能的。例如,MarkdownRemark 总是有一个 File 作为父类型,因此您也可以访问 File 节点中的字段。您也可以多层嵌套,例如 src/pages/blog/{Post.parent__(MarkdownRemark)__parent__(File)__name}.js。
src/pages/blog/{MarkdownRemark.parent__(File)__name}.js 将生成以下查询:
集合路由组件
集合路由组件会接收两个动态变量:每个页面的节点的 id 和 URL 路径作为 params。params 会作为 props.params 传递给组件,id 会作为 props.pageContext.id 传递。
两者都会作为变量传递给组件的 GraphQL 查询,因此您可以查询节点的字段。页面查询(包括变量的使用)将在 使用 GraphQL 查询页面数据 中更深入地进行解释。
例如:
对于页面 src/pages/{Product.name}/{Product.coupon}.js,在 {Product.coupon}.js 中,您将可以访问 props.params.name 和 props.params.coupon。
如果您需要为集合中的某些节点创建页面(例如,过滤掉类型为 "Food" 的产品)或自定义传递给查询的变量,则应改用 createPages API,因为文件系统路由 API 目前不支持此功能。
路由和链接
Gatsby 会对从集合页面创建的每个路由进行“slugify”(通过使用 sindresorhus/slugify)。换句话说:如果您有一个名为 src/pages/wholesome/{Animal.slogan}.js 的路由,其中 slogan 是 I ♥ Dogs,则最终 URL 将是 /wholesome/i-love-dogs。Gatsby 会将字段转换为人类可读的 URL 格式,同时去除无效字符。您可以为 src/pages 路径调整 gatsby-plugin-page-creator 来配置 slugify。
当您想链接到集合路由页面时,可能并不总是清楚如何从头开始构建 URL。
为了解决这个问题,Gatsby 会自动为集合页面使用的每个类型添加一个 gatsbyPath 字段。 gatsbyPath 字段必须接受一个 filePath 参数,它试图解析该文件路径。这是必需的,因为一种类型可能被用于多个集合页面。
使用 filePath 参数时,有一些通用的语法要求:
- 路径必须是绝对路径(以
/开头)。 - 您必须省略文件扩展名。
- 您必须省略
src/pages前缀。 - 您的路径不得包含
index。
gatsbyPath 示例
假设 Product 类型在两个页面中使用:
src/pages/products/{Product.name}.jssrc/pages/discounts/{Product.name}.js
如果您想从主页链接到 products/{Product.name} 和 discounts/{Product.name} 路由,您将拥有一个如下所示的组件:
通过使用 别名,您可以多次使用 gatsbyPath。
创建仅客户端路由
如果您有不在 Gatsby 中存在的动态数据,请使用 仅客户端路由。这可能是一个用户设置页面,或其他在构建时 Gatsby 未知的动态内容。在这些情况下,您通常会创建一个带有或多个动态段的路由,以便从服务器查询数据来渲染您的页面。
语法(仅客户端路由)
您可以在文件路径中使用方括号([ ])来标记 URL 的任何动态段。例如,为了编辑用户,您可能需要一个像 /user/:id 这样的路由来获取传递到 URL 的任何 id 的数据。
src/pages/users/[id].js将生成一个像/users/:id这样的路由src/pages/users/[id]/group/[groupId].js将生成一个像/users/:id/group/:groupId这样的路由
Splat 路由
Gatsby 还支持 splat(或通配符)路由,这些路由将匹配 任何 在 splat 之后的内容。这些不太常见,但仍然有其用途。在文件路径中使用方括号中的三个点([...])可以将页面标记为 splat 路由。您还可以通过在三个点后添加名称来命名您的页面接收的参数([...myNameKey])。
例如,假设您正在从 S3 渲染图像,并且 URL 实际上是 AWS 资源的键。以下是如何创建您的文件:
src/pages/image/[...].js将生成一个像/image/*这样的路由。*在您的页面的接收属性中以*的键名访问。src/pages/image/[...awsKey].js将生成一个像/image/*awsKey这样的路由。*awsKey在您的页面的接收属性中以awsKey的键名访问。
Splat 路由可能无法与常规仅客户端路由位于同一目录中。
示例
文件名中的动态段(方括号之间的部分)将被填充并作为 props.params 对象提供给您的组件。例如:
config 函数
在文件系统路由模板中,您可以导出一个名为 config 的异步函数。您可以使用此函数来:
- 将页面标记为延迟或非延迟(请参阅 延迟静态生成 API 参考)
在您的模板内
当您导出一个异步 config 函数时,Gatsby 会评估返回的对象,并可以选择性地运行在外层函数中定义的任何 GraphQL 查询。您不能在内层函数中运行 GraphQL 查询。
params 参数是一个包含 URL 路径的对象,请参阅 上面的说明。
config 的内层函数可以返回一个只包含一个键的对象:
defer:一个布尔值,表示页面是否应标记为延迟。
请阅读 延迟静态生成指南 以查看真实示例。
示例用例
请查看 route-api 示例 以获取更多详细信息。
集合路由 + 回退
通过结合使用集合路由和仅客户端路由,您可以在用户尝试访问集合路由中不存在(尚未)的集合项的 URL 时,创建无缝的体验。考虑这两个文件路径:
src/pages/products/{Product.name}.js(集合路由)src/pages/products/[name].js(仅客户端路由,回退)
集合路由将在 构建 时创建所有可用的产品页面。如果您添加了一个新的产品要链接,但只定期构建您的站点,您将需要一个回退。通过使用仅客户端路由作为回退,您可以在重新构建站点之前,在客户端加载产品的必要信息。
同样,回退页面也可用于产品不存在时,您希望显示一些有用的信息(例如 404 页面)。
使用一个模板创建多个路由
通过将路由的模板/视图放入可重用组件中,您可以显示相同的信息在不同的路由下。看这个例子:
您想显示产品信息,该信息可以通过名称和 SKU 访问,但具有相同的样式。首先创建两个文件路径:
src/pages/products/{Product.name}.jssrc/pages/products/{Product.meta__sku}.js
在 src/view/product-view.js 创建一个接收 product prop 的视图组件。在两个集合路由中使用该组件,例如:
您可以将相同的代码复制到 src/pages/products/{Product.meta__sku}.js 文件中。
纯粹的仅客户端应用
如果您希望您的 Gatsby 应用 100% 仅在客户端运行,您可以将文件放在 src/pages/[...].js 来捕获所有请求。有关更多详细信息,请参阅 client-only-paths 示例。