Gatsby 中文教程

1. 什么是 Gatsby?

Gatsby 是一个基于 React 的开源静态站点生成器 (SSG),专注于构建高性能、SEO 友好的网站。它由 Kyle Mathews 创建,通过 GraphQL 层连接数据源和 React 组件,生成完全静态的 HTML、CSS 和 JavaScript 文件。

1.1 Gatsby 的核心优势

  • 极致性能:预加载资源、代码拆分、图像优化等技术,提供接近瞬时的页面加载体验。
  • SEO 友好:静态生成的 HTML 对搜索引擎非常友好,提高网站排名。
  • 丰富的插件生态:通过插件系统集成各种数据源和功能。
  • GraphQL 数据层:统一的数据查询接口,简化数据获取和管理。
  • 开发体验:热模块替换、快速刷新等功能,提高开发效率。
  • 部署便捷:生成的静态文件可以部署到任何静态托管服务。
  • 现代化技术栈:基于 React、GraphQL 和 Webpack,使用最新的前端技术。

2. 安装和初始化

2.1 使用 gatsby-cli 初始化项目

# 安装 gatsby-cli
npm install -g gatsby-cli

# 初始化项目
gatsby new my-gatsby-site

# 进入项目目录
cd my-gatsby-site

# 启动开发服务器
gatsby develop

2.2 选择模板

Gatsby 提供了多种官方模板,可以根据需要选择:

# 使用默认模板
gatsby new my-gatsby-site

# 使用博客模板
gatsby new my-blog https://github.com/gatsbyjs/gatsby-starter-blog

# 使用电商模板
gatsby new my-ecommerce https://github.com/gatsbyjs/gatsby-starter-ecommerce

# 使用文档模板
gatsby new my-docs https://github.com/gatsbyjs/gatsby-starter-docs

2.3 手动安装

如果你想手动安装 Gatsby,可以按照以下步骤:

# 创建项目目录
mkdir my-gatsby-site
cd my-gatsby-site

# 初始化 package.json
npm init -y

# 安装依赖
npm install gatsby react react-dom

# 添加脚本
# 在 package.json 中添加:
# "scripts": {
#   "develop": "gatsby develop",
#   "build": "gatsby build",
#   "serve": "gatsby serve",
#   "clean": "gatsby clean"
# }

# 创建 gatsby-config.js 配置文件
# echo "module.exports = { plugins: [] }" > gatsby-config.js

2.4 验证安装

# 启动开发服务器
gatsby develop

# 访问 http://localhost:8000

# 访问 GraphQL  playground
# http://localhost:8000/___graphql

3. 基本目录结构

Gatsby 项目的默认目录结构如下:

my-gatsby-site/
├── src/             # 源代码目录
│   ├── components/  # React 组件
│   ├── pages/       # 页面组件(自动生成路由)
│   ├── templates/   # 模板组件(用于动态生成页面)
│   ├── images/      # 图像资源
│   ├── styles/      # 样式文件
│   └── utils/       # 工具函数
├── public/          # 构建输出目录
├── static/          # 静态资源(直接复制到输出目录)
├── gatsby-config.js   # Gatsby 配置文件
├── gatsby-node.js     # Node.js API 配置
├── gatsby-browser.js  # 浏览器 API 配置
├── gatsby-ssr.js      # SSR API 配置
├── package.json       # 项目配置文件
└── README.md          # 项目说明文件

4. 核心功能

4.1 页面创建

Gatsby 支持两种创建页面的方式:

4.1.1 文件系统路由

src/pages 目录中创建 React 组件,Gatsby 会自动为其生成路由:

// src/pages/index.js
import React from 'react';

export default function Home() {
  return (
    <div>
      <h1>Hello Gatsby!</h1>
      <p>Welcome to your new Gatsby site.</p>
    </div>
  );
}

// src/pages/about.js
import React from 'react';

export default function About() {
  return (
    <div>
      <h1>About Us</h1>
      <p>This is the about page.</p>
    </div>
  );
}

4.1.2 编程式创建页面

gatsby-node.js 中使用 API 编程式创建页面:

// gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  // 查询数据
  const result = await graphql(`
    query {
      allMarkdownRemark {
        edges {
          node {
            frontmatter {
              path
            }
          }
        }
      }
    }
  `);

  // 创建页面
  result.data.allMarkdownRemark.edges.forEach(({ node }) => {
    createPage({
      path: node.frontmatter.path,
      component: require.resolve('./src/templates/blog-post.js'),
      context: {
        // 传递给模板的数据
        slug: node.frontmatter.path,
      },
    });
  });
};

4.2 数据获取

Gatsby 使用 GraphQL 来获取和管理数据:

4.2.1 页面数据查询

在页面组件中使用 pageQuery 静态属性定义 GraphQL 查询:

// src/pages/blog.js
import React from 'react';
import { graphql } from 'gatsby';

export default function Blog({ data }) {
  const posts = data.allMarkdownRemark.edges;

  return (
    <div>
      <h1>Blog</h1>
      <ul>
        {posts.map(({ node }) => (
          <li key={node.id}>
            <h2>{node.frontmatter.title}</h2>
            <p>{node.excerpt}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export const pageQuery = graphql`
  query BlogQuery {
    allMarkdownRemark {
      edges {
        node {
          id
          frontmatter {
            title
            date
          }
          excerpt
        }
      }
    }
  }
`;

4.2.2 组件数据查询

在非页面组件中使用 useStaticQuery 钩子获取数据:

// src/components/Header.js
import React from 'react';
import { useStaticQuery, graphql } from 'gatsby';

export default function Header() {
  const data = useStaticQuery(graphql`
    query HeaderQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `);

  return (
    <header>
      <h1>{data.site.siteMetadata.title}</h1>
    </header>
  );
}

4.3 插件系统

Gatsby 的插件系统允许你扩展核心功能,以下是一些常用的插件:

4.3.1 数据源插件

  • gatsby-source-filesystem:从文件系统读取数据
  • gatsby-source-wordpress:从 WordPress 获取数据
  • gatsby-source-contentful:从 Contentful CMS 获取数据
  • gatsby-source-strapi:从 Strapi CMS 获取数据

4.3.2 转换插件

  • gatsby-transformer-remark:处理 Markdown 文件
  • gatsby-transformer-json:处理 JSON 文件
  • gatsby-transformer-yaml:处理 YAML 文件
  • gatsby-transformer-sharp:处理图像

4.3.3 功能插件

  • gatsby-plugin-image:图像优化
  • gatsby-plugin-sharp:图像处理
  • gatsby-plugin-react-helmet:管理文档头部
  • gatsby-plugin-sitemap:生成站点地图
  • gatsby-plugin-robots-txt:生成 robots.txt
  • gatsby-plugin-manifest:生成 PWA 清单
  • gatsby-plugin-offline:启用离线功能

4.4 图像优化

Gatsby 提供了强大的图像优化功能,通过 gatsby-plugin-imagegatsby-plugin-sharp 插件实现:

// src/components/OptimizedImage.js
import React from 'react';
import { StaticImage } from 'gatsby-plugin-image';

export default function OptimizedImage() {
  return (
    <div>
      <h2>优化后的图像</h2>
      <StaticImage
        src="../images/example.jpg"
        alt="Example image"
        width={800}
        height={600}
        placeholder="blurred"
        quality={90}
      />
    </div>
  );
}

对于动态图像,可以使用 gatsbyImageData

// src/components/DynamicImage.js
import React from 'react';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

export default function DynamicImage({ imageData }) {
  const image = getImage(imageData);
  
  return (
    <GatsbyImage
      image={image}
      alt="Dynamic image"
    />
  );
}

4.5 路由和链接

Gatsby 使用 gatsby-link 组件实现客户端路由:

// src/components/Nav.js
import React from 'react';
import { Link } from 'gatsby';

export default function Nav() {
  return (
    <nav>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/blog">Blog</Link></li>
      </ul>
    </nav>
  );
}

5. 高级特性

5.1 页面预加载

Gatsby 会自动预加载视口中的链接,提高导航速度:

// src/components/BlogPost.js
import React from 'react';
import { Link } from 'gatsby';

export default function BlogPost({ post }) {
  return (
    <div>
      <h2>{post.title}</h2>
      <p>{post.excerpt}</p>
      {/* 此链接会被自动预加载 */}
      <Link to={`/blog/${post.slug}`}>Read more</Link>
    </div>
  );
}

5.2 代码拆分

Gatsby 自动进行代码拆分,减少初始加载体积:

// src/components/LazyComponent.js
import React, { lazy, Suspense } from 'react';

// 动态导入组件
const HeavyComponent = lazy(() => import('./HeavyComponent'));

export default function LazyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

5.3 PWA 支持

通过插件启用 PWA 功能:

// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: `My Gatsby Site`,
        short_name: `Gatsby Site`,
description: `A Gatsby site`,
        start_url: `/`,
        background_color: `#ffffff`,
        theme_color: `#0070f3`,
        display: `standalone`,
        icon: `src/images/icon.png`,
      },
    },
    `gatsby-plugin-offline`,
  ],
};

5.4 国际化

使用插件实现国际化支持:

# 安装插件
npm install gatsby-plugin-intl
// gatsby-config.js
module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-intl`,
      options: {
        path: `${__dirname}/src/intl`,
        languages: [`en`, `zh`],
        defaultLanguage: `en`,
        redirect: true,
      },
    },
  ],
};
// src/intl/en.json
{
  "title": "Hello",
  "description": "Welcome to my site"
}

// src/intl/zh.json
{
  "title": "你好",
  "description": "欢迎访问我的网站"
}

// src/components/TranslatedComponent.js
import React from 'react';
import { useIntl } from 'gatsby-plugin-intl';

export default function TranslatedComponent() {
  const intl = useIntl();
  
  return (
    <div>
      <h1>{intl.formatMessage({ id: 'title' })}</h1>
      <p>{intl.formatMessage({ id: 'description' })}</p>
    </div>
  );
}

6. 最佳实践

6.1 性能优化

  • 使用静态图像:对于固定图像,使用 StaticImage 组件。
  • 优化动态图像:对于动态图像,使用 gatsbyImageData 并设置适当的参数。
  • 代码拆分:使用动态导入减少初始加载体积。
  • 缓存策略:合理设置缓存头,减少重复请求。
  • 减少第三方脚本:只加载必要的第三方脚本,避免阻塞页面加载。
  • 使用字体子集:只包含使用的字符,减少字体文件大小。

6.2 目录结构

my-gatsby-site/
├── src/             # 源代码目录
│   ├── components/  # 可复用组件
│   │   ├── ui/      # UI 组件
│   │   └── layout/  # 布局组件
│   ├── pages/       # 页面组件
│   ├── templates/   # 模板组件
│   ├── images/      # 图像资源
│   ├── styles/      # 样式文件
│   ├── utils/       # 工具函数
│   └── intl/        # 国际化文件
├── static/          # 静态资源
├── gatsby-config.js   # Gatsby 配置
├── gatsby-node.js     # Node.js API 配置
├── gatsby-browser.js  # 浏览器 API 配置
├── gatsby-ssr.js      # SSR API 配置
└── package.json       # 项目配置

6.3 部署策略

Gatsby 生成的静态文件可以部署到任何静态托管服务:

6.3.1 Netlify

  1. 将代码推送到 GitHub、GitLab 或 Bitbucket
  2. 在 Netlify 上导入项目
  3. 配置构建命令:gatsby build
  4. 配置发布目录:public
  5. 部署完成后获得一个 URL

6.3.2 Vercel

  1. 将代码推送到 GitHub、GitLab 或 Bitbucket
  2. 在 Vercel 上导入项目
  3. 配置构建命令:gatsby build
  4. 配置发布目录:public
  5. 部署完成后获得一个 URL

6.3.3 GitHub Pages

  1. 安装 gh-pages 插件:npm install gh-pages
  2. package.json 中添加脚本:&quot;deploy&quot;: &quot;gatsby build &amp;&amp; gh-pages -d public&quot;
  3. 运行部署命令:npm run deploy
  4. 部署到 https://&lt;username&gt;.github.io/&lt;repository-name&gt;

6.4 安全最佳实践

  • 环境变量:使用 .env 文件存储敏感信息
  • 输入验证:验证用户输入,防止 XSS 和注入攻击
  • 依赖管理:定期更新依赖,修复安全漏洞
  • HTTPS:确保网站使用 HTTPS 协议
  • 内容安全策略:配置适当的 CSP 头,防止恶意脚本执行

7. 常见问题与解决方案

7.1 数据查询问题

问题:GraphQL 查询返回空数据

解决方案

  • 检查数据源插件是否正确配置
  • 确保数据文件存在且格式正确
  • 在 GraphiQL 中测试查询,确认语法正确
  • 检查 gatsby-node.js 中的数据处理逻辑

7.2 图像优化问题

问题:图像不显示或优化失败

解决方案

  • 确保安装了 gatsby-plugin-imagegatsby-plugin-sharp
  • 检查图像路径是否正确
  • 确保图像文件存在
  • 检查插件配置是否正确

7.3 构建问题

问题gatsby build 失败

解决方案

  • 检查控制台错误信息,定位具体问题
  • 确保所有依赖都已正确安装
  • 检查 gatsby-config.jsgatsby-node.js 中的配置
  • 清除缓存后重试:gatsby clean &amp;&amp; gatsby build

7.4 部署问题

问题:部署后页面空白

解决方案

  • 检查浏览器控制台错误信息
  • 确保所有资源路径正确(特别是静态资源)
  • 检查路由配置是否正确
  • 确保使用了相对路径或正确的绝对路径

7.5 性能问题

问题:页面加载缓慢

解决方案

  • 使用 Gatsby 分析工具:gatsby build --analyze
  • 优化图像:使用 StaticImagegatsbyImageData
  • 减少初始加载体积:使用代码拆分和动态导入
  • 优化第三方脚本:延迟加载非关键脚本
  • 启用浏览器缓存:配置适当的缓存头

8. 总结

Gatsby 是一个功能强大的静态站点生成器,它通过预加载、代码拆分、图像优化等技术,提供了极致的性能体验。同时,它的插件生态系统和 GraphQL 数据层,使得开发和数据管理变得更加简单和高效。

通过本教程,你应该已经了解了 Gatsby 的基本概念、核心功能和最佳实践。Gatsby 非常适合构建博客、企业网站、电商网站等各种类型的静态网站,它的现代化技术栈和优秀的开发体验,使得前端开发变得更加愉悦和高效。

随着 Gatsby 的不断发展,新的特性和改进不断推出,建议你关注官方文档和更新日志,保持对最新功能的了解。无论你是构建个人网站还是企业应用,Gatsby 都能为你提供出色的解决方案。

« 上一篇 Nuxt.js 中文教程 下一篇 » Eleventy 中文教程