菜单

热重载与开发服务器

相关源文件

介绍

Gatsby 的热重载和开发服务器通过在文件更改时自动刷新内容,无需完全重新加载页面,从而提供了无缝的开发体验。此系统是 Gatsby 开发工作流的核心,可在构建站点时提供实时反馈。

有关开发相关的 CLI 命令的信息,请参阅 CLI 和命令。有关开发环境中的错误处理信息,请参阅 错误处理

架构概述

开发服务器和热重载架构由几个相互关联的组件组成,它们协同工作以提供开发体验。

来源:packages/gatsby/src/commands/develop-process.ts77-152 packages/gatsby/src/utils/start-server.ts67-887 packages/gatsby/src/utils/websocket-manager.ts31-233

开发服务器初始化

运行 gatsby develop 时,会发生以下初始化序列

服务器初始化过程

  1. develop-process.ts 模块创建一个 Express 应用并初始化一个状态机
  2. 状态机经过各种状态转换,最终调用 startServer()
  3. startServer() 使用热模块替换配置 webpack
  4. 设置 Express 中间件,包括 webpack-dev-middleware 和 webpack-hot-middleware
  5. 配置 GraphQL、页面数据和 HTML 渲染的路由
  6. 初始化 WebsocketManager 以实现实时更新

来源:packages/gatsby/src/commands/develop-process.ts77-152 packages/gatsby/src/utils/start-server.ts67-180 packages/gatsby/src/services/start-webpack-server.ts24-67

客户端热重载实现

在客户端,热重载由几个关键组件处理

客户端实现

  1. app.js 是开发 bundle 的入口点
  2. 它通过 socketIo.js 与服务器建立 WebSocket 连接
  3. DevLoader 类通过特定于开发的函数扩展了基础的 BaseLoader
  4. 当通过 WebSocket 收到更新时,相应的处理程序会处理这些更新
  5. 页面组件和数据会响应更改而更新

来源:packages/gatsby/cache-dir/app.js1-207 packages/gatsby/cache-dir/dev-loader.js30-254

热更新流程

当文件更改时,会发生以下事件序列

不同类型的更新会触发特定的处理程序

  1. 静态查询更新:当静态查询结果更改时,DevLoader 会更新其缓存并重新渲染组件
  2. 页面查询更新:当页面查询结果更改时,页面数据会更新,页面会重新渲染
  3. 页面内容更新:当组件更改时,webpack 的热模块替换会更新组件
  4. 过时页面数据:当数据过时时,会从服务器重新获取

来源:packages/gatsby/src/services/start-webpack-server.ts40-128 packages/gatsby/src/utils/websocket-manager.ts156-230 packages/gatsby/cache-dir/dev-loader.js56-254

WebsocketManager

WebsocketManager 类负责处理服务器和客户端之间的实时通信

WebsocketManager

  1. 跟踪活动的客户端连接以及它们正在查看的路径
  2. 向客户端发送不同类型的更新(查询结果、错误等)
  3. 维护静态查询结果的记录
  4. 当页面数据过时时通知客户端

来源:packages/gatsby/src/utils/websocket-manager.ts31-233 packages/gatsby/src/utils/start-server.ts854-886

DevLoader 实现

DevLoader 通过特定于开发的增强功能扩展了 Gatsby 的基础加载器

DevLoader

  1. 跟踪未找到的页面以避免不必要的重新获取
  2. 处理不同类型内容(页面查询、静态查询)的热更新
  3. 管理开发环境的页面数据缓存
  4. 与 socket.io 连接协调以接收更新

来源:packages/gatsby/cache-dir/dev-loader.js30-254 packages/gatsby/cache-dir/loader.js112-317

开发状态机

开发过程由一个状态机管理,该状态机协调开发的各个阶段

状态机

  1. 管理开发不同阶段之间的转换
  2. 处理文件更改、节点变异和 webhook 请求等事件
  3. 确保必要时运行查询
  4. 与 webpack 协调编译和热更新

来源:packages/gatsby/src/state-machines/develop/index.ts23-584 packages/gatsby/src/state-machines/develop/actions.ts1-227

状态持久化和缓存

Gatsby 在开发服务器重启之间持久化状态以提高性能

持久化机制

  1. 在发生更改时将 Redux store 状态保存到磁盘
  2. 分块大型数据集(节点、页面)以避免内存限制
  3. 服务器重启时恢复状态
  4. 检测到插件、gatsby-config.js 和 gatsby-node.js 的更改,以便在需要时清除缓存

来源: packages/gatsby/src/redux/index.ts132-158 packages/gatsby/src/redux/persist.ts214-266 packages/gatsby/src/services/initialize.ts296-459

开发标志和优化

Gatsby 包含多个标志以增强开发体验

标志名称环境变量描述
FAST_DEVGATSBY_EXPERIMENTAL_FAST_DEV启用所有旨在提高开发服务器启动时间的实验性功能
DEV_SSRGATSBY_EXPERIMENTAL_DEV_SSR在开发过程中服务器端渲染页面,以帮助检测 SSR 错误
PRESERVE_FILE_DOWNLOAD_CACHEGATSBY_EXPERIMENTAL_PRESERVE_FILE_DOWNLOAD_CACHE在重启之间保留下载的文件以加快开发速度

这些标志可以通过以下方式启用

  1. 环境变量
  2. 在 gatsby-config.js 中进行配置
  3. 命令行参数

来源: packages/gatsby/src/utils/flags.ts80-155 packages/gatsby/src/services/initialize.ts40-61

开发服务器路由

开发服务器公开了几个特殊路由

路由目的
/__open-stack-frame-in-editor在编辑器中打开特定行处的源文件
/__original-stack-frame返回转译代码的原始源位置
/__file-code-frame返回特定文件位置的格式化代码框
/__refresh允许从外部系统触发数据刷新
/___graphql用于探索和测试 GraphQL 查询的 GraphiQL 界面
/page-data/:pagePath/page-data.json提供特定页面的页面数据

这些路由支持各种开发功能,包括错误报告、调试和数据探索。

来源: packages/gatsby/src/utils/start-server.ts168-261 packages/gatsby/src/utils/start-server.ts262-379 packages/gatsby/src/utils/start-server.ts790-853

处理文件更改

当源文件发生变化时,Gatsby 会根据文件类型触发不同的操作

文件监视系统

  1. 对 JavaScript 和 CSS 文件使用 webpack 的文件监视
  2. 对其他文件类型(html.js、gatsby-ssr.js 等)使用 chokidar
  3. 根据文件类型触发适当的重新构建
  4. 通过 websocket 连接将更新发送给客户端

来源: packages/gatsby/src/utils/start-server.ts865-876 packages/gatsby/src/bootstrap/requires-writer.ts342-383

结论

Gatsby 的热重载和开发服务器通过高效地检测更改并在浏览器中实时更新,提供无缝的开发体验。该系统结合了

  1. Webpack 对 JavaScript/CSS 更改的热模块替换
  2. 用于实时通信的 WebsocketManager
  3. 用于客户端更新处理的 DevLoader
  4. 用于协调开发流程的状态机
  5. Redux 用于状态管理
  6. 文件持久化以加快重启速度

这些组件协同工作,创建了一个响应式的开发环境,最大限度地减少构建时间和提高生产力。