- 前端
- 静态站点
- Web框架
【免费下载链接】gatsby
React-based framework with performance, scalability, and security built in.
导读
Gatsby Themes 是 Gatsby 对传统网站模板的一次创新重构:它把"预配置的功能 + 数据源 + UI 代码"打包成可独立升级、可任意组合的 npm 包。本篇教程将以gatsby-theme-blog、gatsby-theme-notes和@pauliescanlon/gatsby-mdx-embed三个主题为例,完整演示如何在单个站点中组合多个主题,并通过组件 Shadowing(组件阴影)与 Theme-UI 定制样式与布局。读完本文,你将掌握多主题组合的配置方法、内容目录的约定、basePath路由拆分、组件阴影的覆盖机制,以及如何用主题组合出一个"博客 + 笔记 + 视频嵌入 + 自定义导航"的一体化站点。
本仓库在 examples/using-multiple-themes 目录下提供了与本教程配套的完整可运行示例,文中的代码片段即取自该示例,完整源码可随时对照查看。
前置知识
本教程假设你已经具备以下基础:
- 理解 Gatsby 基础概念(页面、插件、GraphQL 查询等基本用法);
- 已经了解什么是 Gatsby Themes——简单说,主题就是包含
gatsby-config.js、并带入了预配置功能、数据源和 UI 代码的插件,可以理解为"可组合的独立 Gatsby 站点"。
若对主题概念还比较陌生,建议先阅读仓库内的 What Are Gatsby Themes? 与 Using Multiple Gatsby Themes 两篇文档。
创建新站点
使用 hello-world starter 创建新站点并进入目录:
gatsby new multiple-themes https://github.com/gatsbyjs/gatsby-starter-hello-world cd multiple-themesgatsby new会从 starter 拉取一个最小可运行的 Gatsby 项目骨架,后续所有主题相关配置都将写在这个项目的gatsby-config.js中。
安装并组合两个主题
本步骤将gatsby-theme-blog(博客主题)与gatsby-theme-notes(笔记主题)组合进同一个站点。
1. 安装主题
npm install gatsby-theme-blog gatsby-theme-notes主题本质上是 npm 包,安装后即可像普通插件一样被gatsby-config.js引用;同时它们也具备版本化升级能力——上游主题发布新版本后,只需升级站点中的依赖版本即可同步获得更新。
2. 编辑gatsby-config.js
将主题加入plugins数组,并更新站点元数据:
module.exports = { siteMetadata: { title: `Your Site Title`, description: `A description for your blazing fast site, using multiple themes!`, author: `Your name`, social: [ { name: `Twitter`, url: `https://twitter.com/gatsbyjs`, }, { name: `GitHub`, url: `https://github.com/gatsbyjs`, }, ], }, plugins: [ { resolve: `gatsby-theme-blog`, options: { basePath: `/blog`, }, }, { resolve: `gatsby-theme-notes`, options: { basePath: `/notes`, }, }, ], }这里的关键是basePath选项:它决定了主题生成的内容挂在哪个 URL 前缀下。gatsby-theme-blog的内容被安置到/blog,gatsby-theme-notes的内容被安置到/notes,两个主题在同一站点内各占一段路由,互不干扰——这正是主题可组合性的直观体现。对照仓库中的示例配置 examples/using-multiple-themes/gatsby-config.js 可以看到完全一致的用法(示例中博客主题最终使用了默认的/作为basePath)。
3. 运行站点
gatsby develop4. 验证结果
打开http://localhost:8000查看当前站点内容。
添加内容
两个主题会在站点根目录自动创建各自的内容文件夹(这是主题的约定:gatsby-theme-blog读取content/posts,gatsby-theme-notes读取content/notes)。接下来向这些文件夹添加内容。
添加一篇博客文章
在/content/posts下创建新文件:
--- title: My first blog post date: 2020-02-15 --- Multiple themes are great!添加一条笔记
在/content/notes下创建新文件:
--- title: My first note date: 2020-02-20 --- Multiple themes are awesome!注意原教程中的目录名写为
content/note/hello-notes.md,实际示例仓库中对应文件位于 examples/using-multiple-themes/content/notes/hello-notes.mdx,即笔记内容统一放在content/notes目录下。
这些内容文件采用 MDX 格式(frontmatter 中声明title与date),主题会读取它们并在运行时生成对应页面。
重新启动开发服务器gatsby develop,然后访问:
http://localhost:8000/blog/hello-posts/http://localhost:8000/notes/hello-notes
即可看到新内容。注意 URL 与前面配置的basePath一一对应。
添加头像图片
将一张头像图片放入content/assets/目录。gatsby-theme-blog的 bio(作者简介)组件会读取该目录下的图片作为作者头像,文件名可以是avatar.png或avatar.jpg。示例仓库中对应的资源文件位于 examples/using-multiple-themes/content/assets/avatar.png。
把博客文章放到首页
默认情况下博客挂在/blog,若希望博客直接出现在站点首页/,只需两步:
- 删除现有的
src/pages/index.js文件(把首页控制权让渡给主题); - 修改
gatsby-config.js中博客主题的basePath:
{ resolve: `gatsby-theme-blog`, options: { // basePath 默认为 `/`,因此也可以不写 options,直接写成 `gatsby-theme-blog` basePath: `/`, }, },- 重新运行
gatsby develop验证新首页。
basePath默认值就是/,所以当博客希望占据根路径时,这一项甚至可以省略。示例仓库最终就采用了这种配置,笔记主题则保持basePath: /notes,形成"首页即博客、/notes放笔记"的布局。
组件 Shadowing(组件阴影)
主题提供的组件并非一成不变——通过"组件阴影"机制,你可以在自己的站点里用同名文件覆盖主题内部的组件,从而在不 fork 主题的前提下完成深度定制。核心规则是:把你自己的文件放到与主题内部组件完全相同的相对路径下,Gatsby 会优先加载你的版本。
💡 提示:第一次添加被阴影覆盖的组件时,别忘了停止并重启开发服务器,让构建管线重新识别阴影文件。
阴影bio-content.js
首先定制gatsby-theme-blog中bio组件的文字内容。主题内该文件的路径是components/bio-content.js,因此你需要在站点中创建:
└── src ├── gatsby-theme-blog │ ├── components │ │ ├── bio-content.js // 阴影文件bio 文案可以自由发挥,组件形态大致如下:
import React, { Fragment } from "react" import { Styled } from "theme-ui" export default function BioContent() { return ( <Fragment> Words by <Styled.a href="http://example.com/">Your Name</Styled.a>. <br /> Change me. Your awesome bio, about how great you are! </Fragment> ) }完整版本可对照 examples/using-multiple-themes/src/gatsby-theme-blog/components/bio-content.js。注意这里的 JSX 路径前缀src/gatsby-theme-blog/——gatsby-theme-blog既是主题名,也是阴影目录的命名空间。
阴影 Theme-UI
gatsby-theme-blog与gatsby-theme-notes都使用 Theme-UI 设计令牌(design tokens)来管理样式:颜色、字号、间距等。你同样可以通过组件阴影接管这些设计令牌。
与 bio 的做法一致,需要匹配主题的文件结构,即创建src/gatsby-plugin-theme-ui/index.js:
└── src ├── gatsby-plugin-theme-ui │ ├── index.js // 阴影文件颜色可随意选择,下面是一个示例:
import merge from "deepmerge" import defaultTheme from "gatsby-theme-blog/src/gatsby-plugin-theme-ui/index" export default merge(defaultTheme, { colors: { background: "ghostwhite", text: "black", primary: "mediumvioletred", modes: { dark: { background: "indigo", text: "ghostwhite", primary: "gold", }, }, }, })这里有两个关键点:
- 示例使用了
deepmerge做深合并:你没有覆盖的 Theme-UI 配置会保留主题的默认值,只需声明你想改变的部分; - 由于
gatsby-theme-notes与gatsby-theme-blog共享同一个 Theme-UI 上下文,这份阴影配置会同时作用于两个主题,实现全站视觉统一。
对照示例仓库的 src/gatsby-plugin-theme-ui/index.js,可以看到相同的merge写法。此外,多个主题共存时 Theme-UI 上下文的归属存在约定:从 Using Multiple Gatsby Themes 文档可知,"在gatsby-config.js中最后出现的主题会覆盖其他主题的 Theme-UI 上下文",因此在多主题站点中,把承担主要样式职责的主题放在plugins数组末尾是一个实用的控制手段。
再添加一个小型主题
主题可以是大而全的(如gatsby-theme-blog),也可以只是一小组离散的组件或函数。@pauliescanlon/gatsby-mdx-embed就是后者的典型:它为 MDX 文件增加了直接嵌入社交媒体内容和视频的能力。
1. 安装主题
npm install @pauliescanlon/gatsby-mdx-embed2. 更新gatsby-config.js
把gatsby-mdx-embed作为插件加入数组:
module.exports = { siteMetadata: { // ...siteMetadata 保持不变。 }, plugins: [ `@pauliescanlon/gatsby-mdx-embed`, // 新增 { resolve: `gatsby-theme-blog`, options: { basePath: `/`, }, }, { resolve: `gatsby-theme-notes`, options: { basePath: `/notes`, }, }, ], }注意这里没有配置对象、没有options——当一个主题无需任何配置时,可以像普通字符串插件一样直接声明。示例仓库 examples/using-multiple-themes/gatsby-config.js 最终也是以这种形式引入它的。
3. 在博客文章中嵌入视频
在content/posts/video-post.md中添加 YouTube 视频:
--- title: Jason and Jackson Talk Themes date: 2020-02-21 --- Here is a video about composing and styling themes with J&J! <YouTube youTubeId="6Z4p-qjnKCQ" />重启开发服务器后,这篇博客文章就会渲染出对应的 YouTube 播放器。对应的示例文件见 examples/using-multiple-themes/content/posts/video-post.mdx。由此可见,多主题组合不仅能堆叠"完整站点级"的大主题,也能以极低的成本叠加"组件级"的小主题,粒度完全由你决定。
添加导航菜单
最后,通过组件阴影给站点加上一个跨页面的导航菜单。
1. 在gatsby-config.js中新增menuLinks数组
module.exports = { siteMetadata: { title: `Your Site Title`, description: `A description for your blazing fast site, using multiple themes!`, author: `Your name`, menuLinks: [ { name: `Blog`, url: `/`, }, { name: `Notes`, url: `/notes`, }, ], social: [ // ...social 数组保持不变。 ], }, plugins: [ // ...plugins 数组保持不变。 ], }导航项通过siteMetadata.menuLinks声明,与博客、笔记的basePath一一对应,保证菜单指向真实存在的路由。
2. 创建导航组件
import React from "react" import { Link, useStaticQuery, graphql } from "gatsby" import { Styled, css } from "theme-ui" export default function Navigation() { const data = useStaticQuery( graphql` query SiteMetaData { site { siteMetadata { menuLinks { name url } } } } ` ) const navLinks = data.site.siteMetadata.menuLinks return ( <nav css={css({ py: 2, // paddingTop 与 paddingBottom 的简写 })} > <ul css={css({ display: `flex`, listStyle: `none`, margin: 0, padding: 0, })} > {navLinks.map(link => ( <li css={css({ marginRight: 2, ":last-of-type": { marginRight: 0, }, })} > <Styled.a css={css({ fontFamily: `heading`, fontWeight: `bold`, textDecoration: `none`, ":hover": { textDecoration: `underline`, }, })} as={Link} to={link.url} > {link.name} </Styled.a> </li> ))} </ul> </nav> ) }这个组件演示了两点:一是用useStaticQuery在组件内直接查询siteMetadata.menuLinks,导航数据完全由配置驱动;二是 Theme-UI 的cssprop 与Styled.a的配合——as={Link}让 Gatsby 的<Link>客户端路由能力与 Theme-UI 样式无缝结合。完整实现见 examples/using-multiple-themes/src/components/navigation.js。
3. 阴影header.js
接下来阴影gatsby-theme-blog的header.js。作为起点,可以从主题原始组件复制代码再修改。你的文件结构应为:
└── src ├── gatsby-theme-blog │ ├── components │ │ ├── header.js // 阴影文件4. 导入导航并加入头部
import React from "react" import { css } from "theme-ui" import Navigation from "../../components/navigation" // 新增 export default function Header() { return ( <header> <div css={css({ maxWidth: `container`, mx: `auto`, px: 3, pt: 4, })} > <Navigation /> // 新增 </div> </header> ) }这一步体现了组件阴影的另一个优势:被阴影的组件可以自由组合站点自身的其他组件(这里的Navigation就位于src/components/navigation.js,不在任何主题内部)。示例仓库中的真实 header 还在此基础上进一步保留了主题原有的暗色模式切换、站点标题与 bio 等能力,见 examples/using-multiple-themes/src/gatsby-theme-blog/components/header.js,可作为"从主题原组件出发做增量改造"的完整范本。
5. 验证
运行gatsby develop测试新的导航组件,首页与/notes页面顶部应出现"Blog / Notes"两个导航链接。
总结
通过本教程,你已经掌握了在单个 Gatsby 站点中组合多个主题的完整链路:
- 组合配置:在
gatsby-config.js的plugins数组中同时声明多个主题,并用basePath为每个主题划分路由; - 内容约定:主题按约定从
content/下的固定目录(posts、notes、assets)读取内容与资源; - 组件阴影:通过"同名同路径"规则(
src/gatsby-theme-blog/components/...、src/gatsby-plugin-theme-ui/index.js)覆盖主题组件与 Theme-UI 设计令牌,配合deepmerge做到最小化定制; - 组合粒度:既可以组合博客、笔记这类完整主题,也可以叠加
gatsby-mdx-embed这类组件级小型主题; - 数据驱动 UI:导航等自定义组件可通过
siteMetadata+useStaticQuery声明式渲染。
Gatsby Themes 是对传统网站模板的一次创新式重构——传统 starter 建出的站点与模板立即"脱钩",难以接收上游更新;而主题是可版本化、可升级、可复用的 npm 包,多站点可共享同一主题,多个主题可自由组合。理解并善用它们的潜力,等于给开发者工具箱中又添了一套强大的工具。
继续深入
- 构建一个主题:从零编写自己的可发布主题;
- What Are Gatsby Themes? 与 Using Multiple Gatsby Themes:主题的概念与多主题组合约定;
- 本教程配套的完整示例仓库源码位于 examples/using-multiple-themes,所有最终配置与组件均可直接对照运行。
- 前端
- 静态站点
- Web框架
【免费下载链接】gatsby
React-based framework with performance, scalability, and security built in.
相关推荐
Gatsby 多主题组合实战:在 gatsby-config.js 中组合 gatsby-theme-blog 与 gatsby-theme-notes
Gatsby 多主题组合实战:在 gatsby config.js 中组合 gatsby theme blog 与 gatsby theme notes Gat
前端静态站点Web框架在 Gatsby 中使用多个主题(Multiple Themes):组合 gatsby-theme-blog 与 gatsby-theme-notes 的实战指南
在 Gatsby 中使用多个主题(Multiple Themes):组合 gatsby theme blog 与 gatsby theme notes 的实战指
前端静态站点Web框架Gatsby 主题构建指南:从 Workspace Starter 到 Shadowing 与主题组合
Gatsby 主题构建指南:从 Workspace Starter 到 Shadowing 与主题组合 导读 本文基于 Gatsby 官方文档 building
前端静态站点Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考