ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

将 HTML 静态站点迁移到 Gatsby:从零到生产部署的完整实战指南

2026/9/19 17:53:13 拓冰建站 浏览量
将 HTML 静态站点迁移到 Gatsby:从零到生产部署的完整实战指南 将 HTML 静态站点迁移到 Gatsby从零到生产部署的完整实战指南【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby导读本文基于 Gatsby 官方文档《Porting an HTML Site to Gatsby》以一家虚构的园艺公司 Taylors Tidy Trees 的纯 HTML/CSS 网站为案例完整演示如何将一个传统静态站点迁移到 Gatsby。你将掌握搭建 Gatsby 项目、管理静态资源与全局 CSS、用 Gatsby Head API 与Link组件重构页面结构、用Layout组件消除重复代码、以及构建产物public目录的部署与 path prefix 配置。文章同时结合当前仓库源码揭示路由生成、链接预取、Head 渲染等底层实现原理。适用说明本指南聚焦于静态网站的迁移场景。本指南同样适用于只迁移网站的一部分与现有静态文件共存于同一域名请特别关注文末 托管新网站 一节。更全面的功能讲解请参考仓库中的 Gatsby 教程。准备工作了解示例站点与假设前提示例网站结构本指南要迁移的示例静态网站结构如下website-domain ├── assets │ ├── favicon.ico │ ├── person.png │ ├── normalize.css │ └── style.css ├── index.html ├── 404.html ├── about.html ├── contact.html ├── services │ ├── index.html │ ├── growing.html │ ├── cleaning.html │ └── shrinking.html └── who ├── index.html ├── ellla-arborist.html ├── marin-leafer.html └── sam-surgeon.html假设前提样式方案示例站点使用全局 CSS 文件style.css与normalize.css。Sass 架构参考 Sass 文档或 CSS-in-JS参考 CSS-in-JS 文档也能支持但本指南不展开。无客户端 JS示例站点没有 jQuery 等客户端 JavaScript。如果你的站点包含客户端脚本迁移时若未妥善处理或移除可能在构建期与 Gatsby 冲突可参考 Debugging HTML Builds。开发环境Gatsby 通过编译与构建流程生成生产环境站点也提供针对本地开发优化的工具链。CLI 与开发环境的安装请参考 Gatsby 教程 Part Zero。创建 Gatsby 项目用 hello-world starter 初始化使用 Gatsby 与 npm CLI 创建新项目gatsby new gatsby-site https://github.com/gatsbyjs/gatsby-starter-hello-worldgatsby new会基于 starter 模板生成一个包含基础 Gatsby 应用的gatsby-site文件夹当前仓库中的 hello-world starter 即为该模板src/pages/index.js、static/favicon.ico、gatsby-config.js、package.json等。然后进入目录cd gatsby-site理解src/pages的文件系统路由src文件夹存放站点的大部分前端代码。在 Gatsby 构建流程中src/pages下的每个组件文件都会自动生成一个 HTML 页面。路由规则见 Creating Routes 文档src/pages/contact.js→yoursite.com/contactsrc/pages/information/contact.js→yoursite.com/information/contact例外名为index.js的文件匹配其所在目录的根src/pages/index.js对应yoursite.com/src/pages/information/index.js对应yoursite.com/information新应用中唯一的页面来自src/pages/index.jsimport React from react export default function Home() { return divHello world!/div }启动开发服务器gatsby develop在浏览器访问http://localhost:8000即可看到页面。迁移首页Porting index.html示例站点的index.html如下html langen head titleTaylors Tidy Trees/title link href/assets/favicon.ico relshortcut icon typeimage/x-icon / link relstylesheet typetext/css href/assets/normalize.css / link relstylesheet typetext/css href/assets/style.css / /head body header a href/ classbrand-color logo-textTaylors Tidy Trees/a nav ul lia href/about.htmlAbout/a/li lia href/services/index.htmlServices/a/li lia href/who/index.htmlWho We Are/a/li lia href/contact.htmlContact/a/li /ul /nav /header main h1Welcome To Taylors Tidy Trees/h1 h2We care about trees of all kinds!/h2 /main /body /html下面把它逐块转换成 Gatsby 代码。静态资源static文件夹与 CSS 导入Gatsby 项目中的static文件夹里已有一个favicon.ico即 Gatsby 默认 favicon。static中的所有文件都会被原样服务在应用根路径下把你的 favicon 放进去浏览器刷新即可看到效果。示例中的另一张图片person.png也应移入static供后续使用。Gatsby 的打包系统基于 webpack/Parcel消除了手动编写 CSSlink标签的需要在组件文件中用import引入 CSS 即可Gatsby 会高效地将 CSS 随站点一起交付。创建src/styles文件夹把项目所有 CSS 文件移入并在首页组件中为每个 CSS 文件添加 importimport React from react import ../styles/normalize.css // highlight-line import ../styles/style.css // highlight-line export default function Home() { return divHello world!/div }关于资源处理的更多进阶方式直接 import 图片文件、使用gatsby-plugin-image等见 Importing Assets Into Files 与 Using gatsby-plugin-image。Head 元素Gatsby Head API你可能注意到src/pages/index.js的组件中没有html、head、body——Gatsby 会为每个页面生成默认 HTML 结构并把组件的输出放入body。更多head子元素与 HTML 属性通过 Gatsby Head API 添加见 Gatsby Head API 文档该 API 自gatsby4.19.0起支持。接下来把header与main元素搬进来。复制原head标签的内容但不再需要 CSS 的link标签。Gatsby 组件在代码结构上必须有单一根节点一个常用技巧是用 React Fragment 包裹import React from react import ../styles/normalize.css import ../styles/style.css export default function Home() { return ( header/header main divHello world!/div /main / ) } // highlight-start export const Head () ( titleTaylors Tidy Trees/title link href/favicon.ico relshortcut icon typeimage/x-icon / / ) // highlight-end这里混合了组件与原生 HTML 元素正是JSX模板语言——Gatsby 会把它编译成浏览器可解析渲染的 HTML。从源码层面看Head 中允许的合法标签为link、meta、style、title、base、script、noscript当多个同id元素重复时最后一个生效可用于按页面覆盖全局 favicon 等场景。浏览器端渲染由 head-export-handler-for-browser.js 负责它会将 Head 中渲染的html/body属性提取出来应用到真实 DOM并避免重复渲染造成元素重复。站点导航Link组件Gatsby 自带一组核心构建块Link就是其中之一。它在文件顶部从gatsby包导入替代内部链接的a标签用toprop 代替href属性。站点构建时Link会产出原生 HTML 锚点并附带性能优化在用户触发链接前预取页面内容。将header内容复制过来把a改成Linkimport React from react import { Link } from gatsby // highlight-line import ../styles/normalize.css import ../styles/style.css export default function Home() { return ( header {/* highlight-start */} Link to/ classNamebrand-color logo-text Taylors Tidy Trees /Link nav ul li Link to/aboutAbout/Link /li li Link to/servicesServices/Link /li li Link to/whoWho We Are/Link /li li Link to/contactContact/Link /li /ul /nav {/* highlight-end */} /header main divHello world!/div /main / ) } export const Head () ( titleTaylors Tidy Trees/title link href/favicon.ico relshortcut icon typeimage/x-icon / / )预取的底层实现可见于 gatsby-link 源码GatsbyLink组件利用浏览器IntersectionObserver监听链接是否进入视口一旦进入视口便调用___loader.enqueue(newPathName)预取目标页面资源当链接离开视口时中止未完成的预取。此外它还支持activeClassName、activeStyle、partiallyActive等属性用于高亮当前路由。页面内容class→classNamemain的内容从index.html复制到index.js后基本不用改动但有一点必须处理React 中class是 JavaScript 保留字HTML 的class属性必须重命名为className。再次在浏览器打开http://localhost:8000你应该看到一个视觉完整的首页下一步移植更多页面让链接真正可用。HTML from JavaScriptGatsby 的组件哲学Gatsby 页面的代码是 JavaScript 与 HTML 的混合体。每个页面通常是一个 JavaScript 函数描述给定一组输入props对应的 HTML 块。Gatsby 在构建过程中执行每个页面的 JavaScript 函数产出静态 HTML 文件。组件外观取决于内容与行为的动态程度非常静态的页面几乎全是 HTML 标记外面包一层供 Gatsby 装配的 JavaScript带 props输入与逻辑的组件在 JSX 中穿插更多 JavaScript例如用 GraphQL 数据层 或 从文件导入数据 生成动态标记如相关链接列表。本指南偏向 HTML 一侧以适配静态站点。但尽早用 React 组织客户端 JavaScript 会打开很多未来可能性Gatsby 既能从组件产出静态页面也能在页面加载后下发动态客户端 JavaScript让站点 水合hydration 成完整的 React 应用。迁移子页面Porting pages移植一个子索引页Taylors Tidy Trees 的who区有 4 个团队成员页面其索引页如下html langen head titleTaylors Tidy Trees - Who We Are/title link href/assets/favicon.ico relshortcut icon typeimage/x-icon / link relstylesheet typetext/css href/assets/normalize.css / link relstylesheet typetext/css href/assets/style.css / /head body header a href/ classbrand-color logo-textTaylors Tidy Trees/a nav ul lia href/about.htmlAbout/a/li lia href/services/index.htmlServices/a/li lia href/index.htmlWho We Are/a/li lia href/contact.htmlContact/a/li /ul /nav /header main h1Who We Are/h1 h2These are our staff:/h2 ul lia href/who/ella-arborist.htmlElla (Arborist)/a/li lia href/who/sam-surgeon.htmlSam (Tree Surgeon)/a/li lia href/who/marin-leafer.htmlMarin (Leafer)/a/li /ul /main /body /html对比/index.html与/who/index.html可以看出除了页面标题和main内容几乎所有部分都重复。这正是提取Layout 组件的时机。Layout 组件消除重复结构Gatsby 中构建与样式化页面的基础构建块是Layout组件详见 Layout Components 文档。它包裹页面内容提供所有页面共有的结构。在src下、与src/pages平级创建components文件夹并在其中新建layout.jsimport React from react export default function Layout({ children }) { return ( header/header main{children}/main / ) }与src/pages/index.js一样该文件导出一个返回 JSX 结构的函数但这次函数接收参数组件函数的第一个参数永远是 props 对象组件的内容children可从 props 上取到JSX 中的花括号包裹一个 JavaScript 表达式其结果会被放置到该位置这里即children变量的值。把/index.html与/who/index.html的公共部分从src/index.js复制进Layoutimport React from react import { Link } from gatsby import ../styles/normalize.css import ../styles/style.css export default function Layout({ children }) { return ( header Link to/ classNamebrand-color logo-text Taylors Tidy Trees /Link nav ul li Link to/about.htmlAbout/Link /li li Link to/services/index.htmlServices/Link /li li Link to/who/index.htmlWho We Are/Link /li li Link to/contact.htmlContact/Link /li /ul /nav /header main{children}/main / ) }注意Layout 中的链接暂时保留了.html后缀待各页面迁移到 Gatsby 的文件系统路由后应改为不含扩展名的路径如/about、/who/index.html→/who。现在用Layout创建src/who/index.jsimport React from react import { Link } from gatsby import Layout from ../components/layout export default function Who() { return ( Layout h1Who We Are/h1 h2These are our staff:/h2 ul li Link to/who/ella-arboristElla (Arborist)/Link /li li Link to/who/sam-surgeonSam (Tree Surgeon)/Link /li li Link to/who/marin-leaferMarin (Leafer)/Link /li /ul /Layout ) } export const Head () ( titleTaylors Tidy Trees - Who We Are/title link href/favicon.ico relshortcut icon typeimage/x-icon / / )此时index.js中的 Who We Are 链接应该可以工作了再把index.js页也改用Layoutimport React from react import Layout from ../components/layout // highlight-line export default function Home() { return ( {/* highlight-start */} Layout h1Welcome To Taylors Tidy Trees/h1 h2We care about trees of all kinds!/h2 /Layout {/* highlight-end */} ); }检查 Who We Are 链接是否仍正常工作若不正常确认内容是否如上所示被Layout正确包裹。从源码角度看 Layout 的价值在于Gatsby默认不会自动为页面包裹布局而是遵循 React 的组合模型由页面显式 import 并包裹。这样既能实现多层级布局全局 header/footer 某些页面的侧边栏也能在布局与页面间传递数据。若担心页面切换时导航组件被卸载重挂破坏 CSS 过渡或组件状态可使用wrapPageElementgatsby-browser 与 gatsby-ssr API或 gatsby-plugin-layout。移植其他页面复用Layout组件、复制main内容即可快速移植页面别忘了class→className。Ella 的页面import React from react import { Link } from gatsby import Layout from ../components/layout export default function EllaArborist() { return ( Layout h1Ella - Arborist/h1 h2Ella is an excellent Arborist. We guarantee it./h2 div classNamebio-card img altComically crude stick person sketch src/person.png / pElla/p /div /Layout ); } export const Head () ( titleTaylors Tidy Trees - Who We Are - Ella/title link href/favicon.ico relshortcut icon typeimage/x-icon / / )Marin 与 Sam 的页面结构类似你甚至可以为 Bio Card 再抽一个组件。等services与根级页面都迁移完成后完整的 Gatsby 项目结构如下gatsby-site ├── static │ ├── favicon.ico │ └── person.png ├── src │ ├── styles │ │ ├── normalize.css │ │ └── style.css │ ├── components │ │ └── Layout.js │ └── pages │ ├── index.js │ ├── about.js │ ├── contact.js │ ├── 404.js │ ├── who │ │ ├── index.js │ │ ├── ellla-arborist.js │ │ ├── marin-leafer.js │ │ └── sam-surgeon.js │ └── services │ ├── index.js │ ├── growing.js │ ├── cleaning.js │ └── shrinking.js ├── node_modules ├── .gitignore ├── .prettierignore ├── .prettierrc ├── gatsby-config.js ├── LICENSE ├── package-lock.json ├── package.json └── README.md构建与部署Building DeployingGatsby 构建步骤所有页面迁移完成后站点已能完整镜像原 HTML 站点。停掉开发服务器运行生产构建gatsby build构建完成后编译产物位于public目录。托管新网站构建产物public目录的内容可直接托管在域名根路径/下部署方式与你现有 HTML 站点类似。迁移网站的一部分同样可行——Gatsby 的构建输出可以与现有文件混合部署。如果 Gatsby 站点托管在非根路径如example.com/blog需要告知 Gatsby使构建产物中的页面与资源链接带上路径前缀在gatsby-config.js中配置即可详见 Path Prefix 文档module.exports { pathPrefix: /blog, }这也是迁移站点一部分场景的核心配置只有路径前缀正确Link生成的链接与静态资源 URL 才会指向正确位置。新网站文件结构Gatsby 构建输出中 HTML 与非 JavaScript 资源文件的结构如下注意每个路由都被生成为xxx/index.html配合服务器即可得到无扩展名的美观 URLwebsite-domain ├── favicon.ico ├── person.png ├── index.html ├── 404 │ └── index.html ├── about │ └── index.html ├── contact │ └── index.html ├── services │ ├── index.html │ ├── growing │ │ └── index.html │ ├── cleaning │ │ └── index.html │ ├── shrinking │ │ └── index.html └── who ├── index.html ├── ellla-arborist │ └── index.html ├── marin-leafer │ └── index.html └── sam-surgeon └── index.html下一步Next steps图片与资源Gatsby 支持在页面与组件文件中直接 import 图片等资源见 Importing Assets Into Files并可用 gatsby-plugin-image 获得更深度的优化响应式、占位图、懒加载等。资源交给 Gatsby 管理后就能用插件优化其处理与交付。组件架构Building With Components 解释了 Gatsby 采用 React 组件架构的原因及组件如何融入应用。内容与数据Sourcing Content and Data 是下一步的理想选择——比如用 GraphQL 从gatsby-config.js的siteMetadata中读取站点标题gatsby-config的配置方式见 Gatsby Config API并用 Markdown 编写内容。路由进阶当页面数量变多或需要从数据批量生成页面时可使用 File System Route API如src/pages/products/{Product.name}.js或gatsby-node.js中的 createPages API。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考