12. Gatsby - 静态站点生成
概述
Gatsby 是一个基于 React 的静态站点生成器(SSG),它从数据源(Markdown、CMS、API)获取内容,在构建时生成静态 HTML 文件,提供极快的页面加载速度和优秀的 SEO。
| 维度 | 内容 |
|---|
| What | 基于 React 的静态站点生成器 |
| Why | 构建快速、SEO 友好的静态网站 |
| When | 博客、文档、营销网站等静态内容 |
| Where | Gatsby 项目中使用 |
| Who | 需要静态站点生成的开发者 |
| How | export const query = graphql\query { … }`` |
1. Gatsby 概述
1.1 Gatsby vs Next.js
| 特性 | Gatsby | Next.js |
|---|
| 主要模式 | SSG(静态生成) | SSG + SSR + ISR |
| 数据层 | GraphQL 数据层 | 直接 fetch |
| 插件生态 | 丰富的插件 | 较丰富 |
| 构建时间 | 内容多时较慢 | 较快 |
| 适用场景 | 博客、文档、营销站 | 各类应用 |
1.2 核心概念
// Gatsby 页面组件 import * as React from 'react'; import { graphql } from 'gatsby'; // GraphQL 查询 export const query = graphql` query HomePageQuery { site { siteMetadata { title } } } `; // 页面组件 export default function HomePage({ data }) { return ( <div> <h1>{data.site.siteMetadata.title}</h1> </div> ); }
2. 页面和路由
2.1 文件系统路由
# Gatsby 页面结构 src/ ├── pages/ │ ├── index.js → / │ ├── about.js → /about │ ├── contact.js → /contact │ └── blog/ │ ├── index.js → /blog │ └── {mdx.slug}.js → /blog/:slug
// src/pages/index.js import * as React from 'react'; import { Link } from 'gatsby'; export default function HomePage() { return ( <div> <h1>首页</h1> <Link to="/about">关于我们</Link> </div> ); } // src/pages/about.js export default function AboutPage() { return ( <div> <h1>关于我们</h1> <p>这是关于页面</p> </div> ); }
2.2 动态路由
// src/pages/blog/{mdx.slug}.js import * as React from 'react'; import { graphql } from 'gatsby'; export const query = graphql` query BlogPostQuery($id: String) { mdx(id: { eq: $id }) { frontmatter { title date } body } } `; export default function BlogPost({ data }) { const post = data.mdx; return ( <div> <h1>{post.frontmatter.title}</h1> <div dangerouslySetInnerHTML={{ __html: post.body }} /> </div> ); }
3. 数据层(GraphQL)
3.1 页面查询
// src/pages/blog.js import * as React from 'react'; import { graphql, Link } from 'gatsby'; export const query = graphql` query BlogPageQuery { allMdx(sort: { frontmatter: { date: DESC } }) { nodes { id frontmatter { title date(formatString: "YYYY-MM-DD") } slug } } } `; export default function BlogPage({ data }) { const posts = data.allMdx.nodes; return ( <div> <h1>博客列表</h1> {posts.map(post => ( <article key={post.id}> <h2> <Link to={`/blog/${post.slug}`}> {post.frontmatter.title} </Link> </h2> <p>{post.frontmatter.date}</p> </article> ))} </div> ); }
3.2 静态查询(useStaticQuery)
// src/components/Header.js import * as React from 'react'; import { useStaticQuery, graphql, Link } from 'gatsby'; export default function Header() { const data = useStaticQuery(graphql` query HeaderQuery { site { siteMetadata { title } } } `); return ( <header> <h1> <Link to="/">{data.site.siteMetadata.title}</Link> </h1> </header> ); }
4. 完整示例:博客站点
// gatsby-config.js module.exports = { siteMetadata: { title: '我的博客', description: '分享技术和生活', siteUrl: 'https://example.com', }, plugins: [ 'gatsby-plugin-image', 'gatsby-plugin-sharp', 'gatsby-transformer-sharp', { resolve: 'gatsby-source-filesystem', options: { name: 'blog', path: `${__dirname}/content/blog`, }, }, { resolve: 'gatsby-plugin-mdx', options: { extensions: ['.mdx', '.md'], }, }, ], }; // src/pages/index.js import * as React from 'react'; import { graphql, Link } from 'gatsby'; import Layout from '../components/Layout'; export const query = graphql` query HomePageQuery { allMdx(limit: 6, sort: { frontmatter: { date: DESC } }) { nodes { id frontmatter { title date(formatString: "YYYY-MM-DD") } excerpt slug } } } `; export default function HomePage({ data }) { const posts = data.allMdx.nodes; return ( <Layout> <h1>最新文章</h1> {posts.map(post => ( <article key={post.id}> <h2> <Link to={`/blog/${post.slug}`}> {post.frontmatter.title} </Link> </h2> <p>{post.frontmatter.date}</p> <p>{post.excerpt}</p> </article> ))} </Layout> ); } // src/pages/blog/{mdx.slug}.js import * as React from 'react'; import { graphql } from 'gatsby'; import Layout from '../../components/Layout'; export const query = graphql` query BlogPostQuery($id: String) { mdx(id: { eq: $id }) { frontmatter { title date(formatString: "YYYY-MM-DD") } body } } `; export default function BlogPost({ data }) { const post = data.mdx; return ( <Layout> <article> <h1>{post.frontmatter.title}</h1> <p>{post.frontmatter.date}</p> <div dangerouslySetInnerHTML={{ __html: post.body }} /> </article> </Layout> ); } // src/components/Layout.js import * as React from 'react'; import { useStaticQuery, graphql, Link } from 'gatsby'; export default function Layout({ children }) { const data = useStaticQuery(graphql` query LayoutQuery { site { siteMetadata { title } } } `); return ( <div> <header> <h1> <Link to="/">{data.site.siteMetadata.title}</Link> </h1> <nav> <Link to="/">首页</Link> <Link to="/blog">博客</Link> <Link to="/about">关于</Link> </nav> </header> <main>{children}</main> <footer>© {new Date().getFullYear()}</footer> </div> ); }
5. 总结
核心要点
| 要点 | 说明 |
|---|
| 主要模式 | 静态站点生成(SSG) |
| 数据层 | GraphQL 统一数据层 |
| 路由 | 文件系统路由 + 动态路由 |
| 适用场景 | 博客、文档、营销网站 |
记忆口诀
Gatsby 静态生成快,GraphQL 数据统一来
博客文档最合适,SEO 友好不用猜
6. 相关资源
- Gatsby 官方文档
- Gatsby 教程
- Gatsby 插件库