gatsby-transformer-hjson 使用指南:在 Gatsby 中解析 HJSON 数据并生成 GraphQL 节点

发布时间:2026/9/21 1:54:13
gatsby-transformer-hjson 使用指南:在 Gatsby 中解析 HJSON 数据并生成 GraphQL 节点 gatsby-transformer-hjson 使用指南在 Gatsby 中解析 HJSON 数据并生成 GraphQL 节点【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby导读gatsby-transformer-hjson是 Gatsby 官方仓库中负责把 HJSONHuman JSON文件解析为 JavaScript 对象、并进一步转换为 GraphQL 节点的 transformer 插件。本文以 插件 README 为主线结合插件源码、单元测试与官方示例站点完整讲解安装配置、两种数据组织方式数组对象 / 单个对象的解析算法、GraphQL 查询写法以及底层节点生成原理帮助你在自己的 Gatsby 站点中直接用 HJSON 作为数据源。HJSON 与 gatsby-transformer-hjson 的定位HJSONHuman JSON是 JSON 的一种对人类更友好的扩展格式键可以不加引号、字符串可以省略引号、行尾可以省略逗号、支持//与#注释、支持多行字符串等。Gatsby 生态中通常用gatsby-source-filesystem把磁盘文件变成 File 节点再用各类 transformer 把文件内容解析为结构化数据节点。gatsby-transformer-hjson正是承担把 HJSON 字符串解析成 JavaScript 对象这一步的插件其官方定位是Parses raw HJSON strings into JavaScript objects e.g. from HJSON files. Supports arrays of objects and single objects.它同时支持两类数据结构对象数组一个文件里多条记录和单个对象一个文件一条记录、多个文件并列解析后分别以不同规则命名节点类型。安装与前置条件在项目根目录安装插件npm install gatsby-transformer-hjson从 package.json 可以看到插件运行时依赖hjson^3.2.2作为底层解析器并以gatsby^5.0.0-next为 peerDependencyNode 运行环境要求18.0.0 26。同时你还必须安装并配置gatsby-source-filesystem让它指向存放 HJSON 文件的目录——因为没有 source 插件先把文件读成 File 节点transformer 便无从解析npm install gatsby-source-filesystem在 gatsby-config.js 中注册插件在gatsby-config.js中把gatsby-transformer-hjson加入 plugins 数组// In your gatsby-config.js module.exports { plugins: [gatsby-transformer-hjson], }由于插件不需要任何配置项直接使用字符串形式即可。参考官方示例 examples/using-hjson/gatsby-config.js完整的组合配置通常长这样module.exports { siteMetadata: { title: gatsby-example-using-hjson, }, plugins: [ gatsby-transformer-hjson, { resolve: gatsby-source-filesystem, options: { path: ${__dirname}/src/data/files, name: files, }, }, { resolve: gatsby-source-filesystem, options: { path: ${__dirname}/src/data/letters, name: letters, }, }, ], }这里用两个gatsby-source-filesystem实例分别指向两个数据目录其中一个目录里的 HJSON 是单对象结构、另一个是后续演示用的多文件结构便于对照两种解析算法。解析算法两种数据组织方式插件 README 明确指出你可以选择两种方式组织数据在单个文件里放对象数组或者把单个对象分散到多个文件中。两种方式的节点类型命名规则不同这也是理解整个插件行为的关键。方式一数组对象Array of Objects算法把数组中的每一项转换为一个节点。例如项目中有一个letters.hjson内容为[{ value: a } { value: b } { value: c }]HJSON 允许省略逗号那么会创建以下三个节点;[ { value: a, type: Letters }, { value: b, type: Letters }, { value: c, type: Letters }, ]注意数组模式下节点类型源自文件名README 为了示意简写为Letters。对照源码 src/gatsby-node.js实际类型由_.upperFirst(_.camelCase(\${node.name} HJson))生成即以文件名的驼峰形式拼上HJson后缀——例如文件名为letters.hjson时生成类型是LettersHJson对应 GraphQL 查询allLettersHJson。方式二单个对象Single Object算法把文件根部的单个对象转换为一个节点节点类型基于父目录名。例如项目数据布局如下data/ letters/ a.hjson b.hjson c.hjson其中a.hjson、b.hjson、c.hjson内容分别为value: avalue: bvalue: c则会创建以下三个节点;[ { value: a, type: Letters, }, { value: b, type: Letters, }, { value: c, type: Letters, }, ]同样地源码 src/gatsby-node.js 中该分支使用_.upperFirst(_.camelCase(\${path.basename(node.dir)} HJson))命名类型取**文件所在父目录名**node.dir的 basename驼峰化后拼上HJson。目录名为letters时类型同样为LettersHJson。官方示例 examples/using-hjson/src/data/letters/a.hjson 正是这种目录 单对象文件的结构。源码级解析原理阅读插件唯一的核心实现 src/gatsby-node.js整个解析链路分三步1. 过滤关心的节点shouldOnCreateNodefunction shouldOnCreateNode({ node }) { return ( node.internal.mediaType text/hjson || node.internal.mediaType application/hjson ) }插件只处理 mediaType 为text/hjson或application/hjson的节点。源码注释特别说明目前 mime 包尚未正式识别 HJSON参见 HJSON 的 RFC 1.3 节因此此处是显式枚举两种 mediaType确保.hjson文件能被正确命中。2. 读取内容并解析const content await loadNodeContent(node) const parsedContent HJSON.parse(content)loadNodeContent读取 File 节点原始内容随后交由hjson包的HJSON.parse解析成 JS 对象。注意这里直接HJSON.parse(content)没有任何错误处理分支——HJSON 语法错误会直接抛出构建失败因此数据文件需要保证语法合法。3. 按数据结构分发并创建节点onCreateNodefunction transformObject(obj, id, type) { const contentDigest createContentDigest(obj) const jsonNode { ...obj, id, children: [], parent: node.id, internal: { contentDigest, type, }, } createNode(jsonNode) createParentChildLink({ parent: node, child: jsonNode }) }transformObject把解析出的对象展开到新节点上补充id、children、parent指向源 File 节点与internal.contentDigest、internal.type然后调用createNode写入节点存储并用createParentChildLink建立父子关联——这正是 GraphQL 中可以通过childFilesHJson从 File 节点访问解析结果的原因。节点id的生成也分两种策略数组模式obj.id ? obj.id : createNodeId(\${node.id} [${i}] HJSON)——对象自带id 字段则优先使用否则用「父节点 id 数组下标」派生的稳定 UUID单对象模式parsedContent.id ? parsedContent.id : createNodeId(\${node.id} HJSON)——同样优先使用对象自身的id 字段否则基于父节点 id 生成。从源码结构可以推断在 HJSON 数据中显式提供id字段是控制节点 id 稳定性的推荐做法也有利于增量构建时的内容去重。如何查询How to query无论你选择数组结构还是单对象结构都可以用统一的 GraphQL 查询拿到数据。插件 README 给出的查询示例{ allLettersJson { edges { node { value } } } }返回结果{ allLettersJson: { edges: [ { node: { value: a, }, }, { node: { value: b, }, }, { node: { value: c, }, }, ] } }需要提醒的是README 中allLettersJson属于示意写法。以当前仓库源码为准数组/单对象模式下节点类型都带有HJson后缀实际查询应为allLettersHJson。官方示例 examples/using-hjson/src/pages/index.js 中即可看到两种真实的查询形态export const IndexQuery graphql query { example: file(name: { eq: example }, extension: { eq: hjson }) { data: childFilesHJson { key contains list realist } } letters: allLettersHJson { edges { node { value } } } } 单对象场景通过file(...)过滤到具体文件再用childFilesHJson取解析结果因为父子链接由createParentChildLink建立类型名即FilesHJson多文件单对象场景直接用allLettersHJson查询全部记录。完整示例HJSON 语法与页面渲染仓库自带官方示例站点using-hjson对应 examples/using-hjson/README.md其中 example.hjson 展示了 HJSON 相对 JSON 的主要语法差异是一份很好的速查样本{ // use #, // or /**/ comments, // omit quotes for keys key: 1 // omit quotes for strings contains: everything on this line // omit commas at the end of a line cool: { foo: 1 bar: 2 } // allow trailing commas list: [ 1, 2, ] // use multiline strings realist: My half empty glass, I will fill your empty half. Now you are half full. // and markdown strings markdown: My half **empty glass**, I will fill your *empty half*. Now you are __half full__. }要点归纳键与字符串可省略引号、行尾可省略逗号、允许尾随逗号、支持三种注释语法、支持三引号多行字符串。示例页面 src/pages/index.js 中把key、contains、list数组 join 后展示、realist渲染进表格并把letters记录渲染为列表验证了对象字段、数组字段与多行字符串在 GraphQL 层的可访问性。测试验证解析行为有据可查插件在 src/tests/gatsby-node.js 中提供了两组核心单测直接对应 README 描述的两种算法数组对象测试构造含两个对象的数组一个带id: foo、一个不带断言createNode与createParentChildLink各被调用 2 次。从快照 gatsby-node.js.snap 可见带id的节点沿用id: foo不带id的节点获得createNodeId派生的uuid-from-gatsby两节点的internal.type均为NodeNameHJson由测试节点name: nodeName推导再次印证数组模式类型取自文件名 HJson 后缀。单对象测试构造单对象并设置node.dir为临时目录.../foo/断言只创建 1 个节点且internal.type为FooHJson验证单对象模式类型取自父目录名 HJson 后缀。快照同时展示了父子链接结构createParentChildLink收到{ parent, child }两个参数child 内parent指向源 File 节点 id源节点internal.mediaType为application/hjson。这些测试与快照从行为层面锁定了插件契约后续重构若改动节点类型命名或 id 生成逻辑都会立即被快照测试发现。使用建议与注意事项数据文件必须可被 source 插件识别请确保gatsby-source-filesystem的path指向包含.hjson文件的目录且文件 mediaType 为text/hjson或application/hjson否则shouldOnCreateNode不会放行。HJSON 语法错误会导致构建失败HJSON.parse无容错分支正式数据建议先本地校验。类型命名规则务必牢记数组模式看文件名、单对象模式看父目录名二者都会追加HJson后缀GraphQL 查询用all类型HJson从 File 节点侧则用child类型HJson。善用id字段在 HJSON 数据中提供id可让节点 id 稳定可控有助于内容去重与增量构建。多目录并存像官方示例那样为不同用途的数据配置多个gatsby-source-filesystem实例可以让单对象模式天然按目录聚合出不同的节点类型。综上gatsby-transformer-hjson是一个小而专的 transformer安装一个依赖、注册一个插件、摆好数据目录即可在 Gatsby 的 GraphQL 数据层自由查询 HJSON 内容而其解析行为在 源码 与 快照测试 中均有完整定义非常适合作为理解 Gatsby transformer 插件机制的入门范本。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考