- 前端
- 静态站点
- Web框架
【免费下载链接】gatsby
React-based framework with performance, scalability, and security built in.
本篇指南以 Gatsby 官方仓库中的 using-typescript 示例站点 为主体,讲解如何在 Gatsby 项目中全面落地 TypeScript:从tsconfig.json与gatsby-config.ts的编写,到页面组件的PageProps类型安全、GraphQL 查询类型化,再到gatsby-browser.tsx与gatsby-ssr.tsx中使用GatsbyBrowser/GatsbySSR类型编写 Browser 与 SSR API。读完本文,你将掌握一套可直接复制到自有站点的 TypeScript 化改造方案,并理解 Gatsby 底层如何加载和执行.ts格式的配置文件。
示例站点概览:一套完整的 TypeScript Gatsby 应用
examples/using-typescript是一个最小但结构完整的 TypeScript Gatsby 示例站点,其目录结构如下:
examples/using-typescript/ ├── gatsby-browser.tsx # Browser API(TSX 编写) ├── gatsby-config.ts # 站点配置(TS 编写) ├── gatsby-ssr.tsx # SSR API(TSX 编写) ├── package.json ├── styles.css ├── tsconfig.json └── src/ ├── components/ │ └── layout.tsx # 全局布局组件 └── pages/ ├── 404.tsx # 404 页面 └── index.tsx # 首页(含 GraphQL 查询)这个示例覆盖了 TypeScript 化改造的全部关键位置:
| 文件 | 说明 |
|---|---|
| gatsby-config.ts | 使用GatsbyConfig类型标注的站点配置文件 |
| tsconfig.json | TypeScript 编译配置 |
| src/pages/index.tsx | 使用PageProps泛型 + GraphQL 查询的页面 |
| src/pages/404.tsx | 使用PageProps的 404 页面 |
| src/components/layout.tsx | 带类型标注的布局组件 |
| gatsby-browser.tsx | 使用GatsbyBrowser类型 |
| gatsby-ssr.tsx | 使用GatsbySSR类型 |
依赖与脚本:搭好 TypeScript 开发环境
先看 package.json,它定义了运行与类型检查所需的全部依赖:
{ "scripts": { "start": "gatsby develop", "develop": "gatsby develop", "build": "gatsby build", "type-check": "tsc --noEmit" }, "dependencies": { "gatsby": "next", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@types/node": "^17.0.21", "@types/react": "^17.0.39", "@types/react-dom": "^17.0.11", "typescript": "^4.5.5" } }值得注意的几点:
gatsby以next版本安装:说明该示例跟随 Gatsby 的预发布版本进行验证,实际项目中建议按官方发布线固定版本。- 三个
@types/*包:@types/react与@types/react-dom为 React 提供类型定义,@types/node为 Node.js 全局 API(如process、path)提供类型,三者是 TSX 组件与 Gatsby Node API 正常编译的前提。 type-check脚本:tsc --noEmit只做类型检查、不产出编译产物,可在 CI 或 pre-commit 阶段快速验证全站类型正确性,这也是 TypeScript 化项目建议保留的检查手段。
安装依赖后,使用npm run develop启动开发服务器,或npm run build执行生产构建。
配置类型安全:从 gatsby-config.ts 开始
Gatsby 从 2.x 起即可直接使用.ts作为配置文件。示例中的 gatsby-config.ts 演示了标准写法:
import type { GatsbyConfig } from "gatsby" const config: GatsbyConfig = { siteMetadata: { siteName: `Using TypeScript`, sourceUrl: `https://github.com/gatsbyjs/gatsby/tree/master/examples/using-typescript`, }, plugins: [], } export default config关键点:
import type只引入类型:GatsbyConfig是纯类型导入,编译期会被擦除,不会产生运行时开销。export default导出配置对象:Gatsby 加载配置时通过preferDefault处理默认导出(详见下文底层原理)。siteMetadata与plugins均有类型约束:GatsbyConfig接口定义了siteMetadata、plugins、pathPrefix、trailingSlash、graphqlTypegen、jsxRuntime等字段,写错字段名或类型会在编辑器中即时报错。
GatsbyConfig接口定义在 packages/gatsby/index.d.ts,除示例用到的字段外,还包括:
| 字段 | 类型 | 说明 |
|---|---|---|
pathPrefix | string | 站点部署在子路径(如/blog/)时使用 |
trailingSlash | "always" \| "never" \| "ignore" | 控制 URL 尾部斜杠策略 |
assetPrefix | string | 将静态资源托管到独立域名 |
graphqlTypegen | boolean \| GraphQLTypegenOptions | 自动生成 GraphQL 查询类型(见后文扩展方向) |
polyfill | boolean | 是否包含 Promise polyfill |
jsxRuntime | "automatic" \| "classic" | 指定 JSX 编译运行时 |
proxy | Proxy \| Proxy[] | 开发服务器代理配置 |
headers | Array<Header> | 自定义响应头 |
adapter | IAdapter | 部署平台适配器 |
有了这套类型定义,配置文件的字段补全、类型校验都由编辑器与tsc自动完成。
tsconfig.json:TypeScript 编译器配置逐项解读
tsconfig.json 是示例站点的编译器配置,各选项含义如下:
{ "compilerOptions": { "target": "esnext", "lib": ["dom", "esnext"], "jsx": "react", "module": "esnext", "moduleResolution": "node", "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true }, "include": ["./src/**/*"] }逐项说明:
target: "esnext":编译目标为最新 ECMAScript 特性,交由下游打包工具(Gatsby 内部的 webpack/Parcel)进一步转译,避免 TypeScript 层过早降级。lib: ["dom", "esnext"]:启用 DOM 与 ESNext 标准库类型,覆盖浏览器 API 与最新语言特性。jsx: "react":使用经典的 React JSX 运行时。若gatsby-config.ts中设置了jsxRuntime: "automatic",此处可对应改为"react-jsx"。module: "esnext"、moduleResolution: "node":保留 ESM 模块语义,并按 Node 方式解析模块路径。esModuleInterop: true:允许import React from "react"这类默认导入与 CommonJS 模块互操作,示例代码中import * as React from "react"亦依赖该设置。strict: true:开启全部严格模式检查(strictNullChecks、noImplicitAny等),这是类型安全的核心开关。skipLibCheck: true:跳过.d.ts声明文件内部的类型检查,加快编译速度并规避第三方声明文件的兼容问题。include: ["./src/**/*"]:仅将src目录纳入类型检查范围。配置文件(如gatsby-config.ts)由 Gatsby 独立编译,不依赖此include。
页面组件类型安全:PageProps 与 GraphQL 查询
TypeScript 化改造的重头戏是页面组件。Gatsby 为页面组件提供了PageProps泛型类型,定义在 packages/gatsby/index.d.ts:
export type PageProps< DataType = object, PageContextType = object, LocationState = WindowLocation["state"], ServerDataType = object > = { path: string uri: string location: WindowLocation<LocationState> children: undefined params: Record<string, string> pageResources: { ... } data: DataType pageContext: PageContextType }示例首页 src/pages/index.tsx 完整演示了PageProps与 GraphQL 查询的组合:
import * as React from "react" import { graphql, PageProps } from "gatsby" // 你也可以使用 https://github.com/dotansimha/graphql-code-generator // 从 GraphQL schema 生成类型 interface IndexPageProps { site: { siteMetadata: { siteName: string sourceUrl: string } } } const Index = ({ data: { site } }: PageProps<IndexPageProps>) => { return ( <main> <h1>{site.siteMetadata.siteName}</h1> <p className="custom-text"> This example is hosted on <a href={site.siteMetadata.sourceUrl}>GitHub</a>. </p> </main> ) } export default Index export const pageQuery = graphql` query IndexQuery { site { siteMetadata { siteName sourceUrl } } } `这里的核心模式是手动声明查询结果的接口,再通过泛型传递给PageProps:
interface IndexPageProps按 GraphQL 查询的返回形状声明类型(site → siteMetadata → siteName/sourceUrl);- 组件签名
({ data: { site } }: PageProps<IndexPageProps>)让data具备完整类型推导,site.siteMetadata.siteName的访问不再有any风险; pageQuery使用graphql模板标签定义查询,Gatsby 构建时会提取该查询执行。
示例注释还提示了一个更自动化的方向:使用graphql-code-generator从 GraphQL schema 直接生成类型,从而避免手工维护接口与查询形状的一致性。此外,当前版本 Gatsby 还内置了graphqlTypegen配置项(GatsbyConfig中的boolean | GraphQLTypegenOptions,见 index.d.ts),开启后可自动生成查询类型,进一步简化类型维护。
404 页面:零数据页面的类型写法
src/pages/404.tsx 演示了不含 GraphQL 查询的页面如何写类型:
import * as React from "react" import { PageProps } from "gatsby" const NotFound = ({}: PageProps) => <h1>Page Not Found!</h1> export default NotFound未传入泛型参数时,PageProps使用默认的object类型。此写法表明:页面组件的 props 类型应统一使用PageProps,即使该页面没有数据查询,也保持相同的类型约定,便于后续为 404 页添加数据时不改组件签名。
布局组件:children 的类型标注
src/components/layout.tsx 展示了普通组件的类型写法:
import * as React from "react" const Layout = ({ children }: { children: React.ReactNode }) => ( <div className="global-wrapper">{children}</div> ) export default Layout- 使用内联对象类型
{ children: React.ReactNode }声明 props,React.ReactNode覆盖元素、字符串、数组、Fragment 等所有合法子节点类型; - 该布局组件通过
wrapPageElement包裹每个页面(见下节),是整个站点类型化组件体系的基础。
Browser 与 SSR API:GatsbyBrowser / GatsbySSR 类型
Gatsby 的 Browser API(gatsby-browser.tsx)与 SSR API(gatsby-ssr.tsx)同样支持 TypeScript 写法,示例中两者共同使用wrapPageElement包裹页面:
// gatsby-browser.tsx import * as React from "react" import type { GatsbyBrowser } from "gatsby" import Layout from "./src/components/layout" import "./styles.css" export const wrapPageElement: GatsbyBrowser["wrapPageElement"] = ({ element }) => { return <Layout>{element}</Layout> }// gatsby-ssr.tsx import * as React from "react" import type { GatsbySSR } from "gatsby" import Layout from "./src/components/layout" export const wrapPageElement: GatsbySSR["wrapPageElement"] = ({ element }) => { return <Layout>{element}</Layout> }这种写法的精妙之处:
- 通过索引访问类型:
GatsbyBrowser["wrapPageElement"]直接取出接口中对应 API 的类型签名,Gatsby 会自动推导出wrapPageElement回调的参数({ element, props, ... })与返回值类型,无需手写签名; - 一份实现两处复用:浏览器端与 SSR 端使用相同的布局包裹逻辑,保证客户端水合与服务端渲染输出一致;
- 类型定义来源:
GatsbyBrowser与GatsbySSR接口均定义在 packages/gatsby/index.d.ts 与 同文件 SSR 段,其中列出了onClientEntry、onRouteUpdate、wrapRootElement、onPreRenderHTML、replaceHeadComponents等完整 API 及各自的参数结构,可作为编写其他 API 时的类型参考。
同时,styles.css 在gatsby-browser.tsx中被导入,演示了 TypeScript 项目中同样可以引入全局样式资源。
底层原理:Gatsby 如何加载 .ts 配置文件
Gatsby 之所以能直接使用gatsby-config.ts、gatsby-node.ts等 TS 配置文件,得益于 packages/gatsby/src/bootstrap/get-config-file.ts 中实现的两阶段加载策略:
- 优先加载编译产物:
attemptImportCompiled会先尝试从COMPILED_CACHE_DIR(Gatsby 内部使用 Parcel 编译生成的缓存目录)导入已编译的配置模块; - 回退到源码文件:若编译产物不存在,
attemptImportUncompiled再直接导入站点根目录下的原始配置文件,并通过resolveJSFilepath同时解析.js/.ts/.tsx/.jsx等扩展名; - 友好的错误诊断:当原始文件缺失时,
checkTsAndNearMatch会检测是否存在同名.ts文件(用于提示"存在 gatsby-config.ts 但缺少编译产物")、是否存在命名近似的文件、以及配置是否被错误放进了src/目录,并分别抛出带有专属错误码(如10123、10124、10125、10127)的提示信息。
这套流程保证了:开发者写的gatsby-config.ts既能在开发时被直接识别,也能在生产构建中复用编译缓存,而无需手工将配置转成 JS。
运行验证与类型检查
在examples/using-typescript目录下依次执行:
npm install # 安装依赖 npm run type-check # 仅类型检查(tsc --noEmit) npm run develop # 启动开发服务器,访问 http://localhost:8000 npm run build # 生产构建npm run type-check会在不产出任何文件的前提下校验全站类型;develop与build则由 Gatsby 完成 GraphQL 查询提取、页面生成与静态输出。首页渲染的内容(站点名称与示例说明)来自siteMetadata的 GraphQL 查询结果,可直接验证从配置到页面渲染的完整数据链路。
扩展方向:把示例迁移到你的项目
基于该示例,将自有站点 TypeScript 化的最小改造清单如下:
- 安装类型依赖:
typescript、@types/react、@types/react-dom、@types/node; - 添加
tsconfig.json:可直接复用示例中的严格模式配置; - 重命名配置文件:将
gatsby-config.js改为gatsby-config.ts并加上: GatsbyConfig标注;gatsby-node.ts、gatsby-browser.tsx、gatsby-ssr.tsx同理分别使用GatsbyNode、GatsbyBrowser、GatsbySSR类型; - 页面组件统一
PageProps泛型:为每个 GraphQL 查询声明结果接口,或开启graphqlTypegen: true让 Gatsby 自动生成查询类型; - 加入 CI 检查:在 CI 中运行
npm run type-check,把类型错误拦截在合并之前。
需要注意的前提是:示例基于gatsby: next预发布版本与 TypeScript 4.5、React 18.2 验证,迁移到自己的项目时应以实际安装的 Gatsby 版本对应的类型声明(packages/gatsby/index.d.ts)为准。
总结
using-typescript示例虽然体量小,却完整覆盖了 TypeScript 化 Gatsby 站点的所有关键面:类型化的配置文件、严格模式的tsconfig.json、PageProps泛型驱动的页面数据、GatsbyBrowser/GatsbySSR索引类型标注的 API 实现,以及底层对.ts配置文件的编译加载机制。以此为模板,你可以快速为自己的 Gatsby 项目建立完整的类型安全保障。
- 前端
- 静态站点
- Web框架
【免费下载链接】gatsby
React-based framework with performance, scalability, and security built in.
相关推荐
使用 gatsby-source-faker 为 Gatsby 站点生成模拟数据:基于 using-faker 示例的完整实践
使用 gatsby source faker 为 Gatsby 站点生成模拟数据:基于 using faker 示例的完整实践 本文以仓库 examples/u
前端静态站点Web框架Gatsby Minimal TypeScript Starter 上手指南:用 TypeScript 从零搭建 Gatsby 站点
Gatsby Minimal TypeScript Starter 上手指南:用 TypeScript 从零搭建 Gatsby 站点 本篇技术指南围绕 Gats
前端静态站点Web框架基于 Gatsby 构建多语言站点的零依赖 i18n 方案:using-i18n 示例深度解析
基于 Gatsby 构建多语言站点的零依赖 i18n 方案:using i18n 示例深度解析 导读 本文围绕 Gatsby 官方仓库中的 using i18n
前端静态站点Web框架
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考