Gatsby v4.1 发布解析:File System Route API 接入 DSG 与 JSX Runtime 配置
Gatsby v4.1 发布解析File System Route API 接入 DSG 与 JSX Runtime 配置【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby导读gatsby4.1.02021 年 11 月第 1 个版本是本仓库中 Gatsby 核心框架在 v4 时代的重要迭代。本指南围绕官方发布说明 docs/docs/reference/release-notes/v4.1/index.md 展开重点剖析两大新特性在 File System Route API 中通过config()函数启用 Deferred Static GenerationDSG以及在gatsby-config.js中新增jsxRuntime/jsxImportSource配置项。读完本文你将掌握config()函数的完整写法与执行时机、DSG 的工作原理与限制以及如何让 JSX 在无需手动导入 React 的情况下运行并了解本版本附带的关键 bugfix 与性能改进。前置说明本文涉及的文件与代码均来自当前仓库实际内容。v4.1属于 2021 年的历史版本文中源码引用以当前仓库实现为准用于佐证 API 的设计意图与底层机制。一、Deferred Static Generation 概述Deferred Static GenerationDSG是 Gatsby 的渲染选项之一其核心思想是不再于构建阶段生成所有页面而是将非关键页面延迟到首次用户请求时才生成。这样做可以显著缩短大型站点的构建时间——例如拥有大量历史文章、访问频率低的博客站点就能把老文章页面的生成推迟到运行时。DSG 的完整说明见仓库内的 DSG API 参考 与 DSG 使用指南要点如下页面首次请求时属于缓存未命中因为该页面的 HTML/JSON 尚未生成随后在后台生成产物并缓存第二次请求起直接由 CDN 提供缓存响应。直接访问页面返回 HTML通过 Gatsby 的Link组件进行客户端导航时返回 JSON由路由在客户端渲染。DSG 需要运行 NodeJS 服务器当前完全支持gatsby serve命令及 Gatsby Cloud在gatsby develop下 DSG 不生效。延迟页面通过defer键标记默认页面在构建时生成defer缺省为false。在 v4.1 之前启用 DSG 的唯一方式是使用createPageaction 并传入defer: true在gatsby-node.js中。v4.1 的核心变化是File System Route API 模板文件也支持 DSG 了其入口是新增的config()函数。二、核心特性一config()函数让 File System Route API 支持 DSGFile System Route API 允许通过文件名中的花括号语法自动创建动态页面例如src/pages/products/{Product.name}.js会为每个Product节点生成/products/burger这样的路由。其完整语法点号字段、__嵌套字段、( )联合类型、gatsbyPath链接解析等见 file-system-route-api.md。v4.1 在其中引入了一个全新的 API模板内可导出的异步config()函数。2.1config()函数的基本形态config()的典型写法如下来自发布说明中的完整示例文件为src/pages/{MarkdownRemark.fields__slug}.jsximport React from react import { graphql } from gatsby export default function Component(props) { return pre{JSON.stringify(props, null, 2)}/pre } export async function config() { // Get all posts that were created before 2020-10-31 const { data } graphql { oldPosts: allMarkdownRemark( filter: { frontmatter: { date: { lt: 2020-10-31 } } } ) { nodes { fields { slug } } } } // Create a Set for easier comparison/lookup const oldPosts new Set(data.oldPosts.nodes.map(n n.fields.slug)) // Return a function that when called will return a config for FS route pages // (right now only defer is supported) return ({ params }) { return { // Defer pages older than 2020-10-31 defer: oldPosts.has(params.fields__slug), } } } export const pageQuery graphql query BlogPost($id: String!) { markdownRemark(id: { eq: $id }) { html frontmatter { title date(formatString: MMMM DD, YYYY) description } } } 2.2config()的语法规则与执行机制从发布说明与 file-system-route-api.md 的configfunction 章节 可以归纳出以下规则外层异步函数可以执行 GraphQL 查询config()内部可以像页面查询一样使用graphql模板标签查询数据层也可以完全不查询直接使用普通 JavaScript。必须返回一个函数config()返回的内层函数接收params参数并返回配置对象。params与页面组件中props.params是同一对象例如src/pages/{Product.name}.js中可通过params.name取到节点字段值。内层函数中不能运行 GraphQL 查询查询只能放在外层config()中内层仅负责根据params计算并返回配置。当前仅支持defer一个配置键返回对象形如{ defer: boolean }布尔值决定该页面是否被标记为延迟生成。最小化版本——延迟当前 File System Route 模板生成的所有页面export async function config() { return ({ params }) { return { defer: true, } } }2.3 从源码看config()的执行流程config()并非仅在模板里写出来即可Gatsby 在构建阶段会真正加载并执行它。当前仓库中 packages/gatsby/src/utils/page-mode.ts 实现了相关逻辑可以从源码结构看到完整调用链preparePageTemplateConfigs(graphql)第 118-145 行遍历所有组件对声明了config导出的组件通过pageRenderer.getPageChunk({ componentChunkName })拿到页面模板实例然后调用componentInstance.config()获取配置工厂函数并校验其必须是函数否则抛出Unexpected result of config factory...错误最后存入pageConfigMap。resolvePageMode(page, component)第 37-80 行对每个页面调用pageConfigMap中对应的配置函数以page.context.__params作为params传入若返回的pageConfig.defer为布尔值则据此把页面模式解析为DSG或SSG若未命中则回退到页面自身的page.defer判断。materializePageMode()第 89-116 行将 DSG/SSR 页面的mode持久化确保gatsby serve能正确工作。由此可以推断config()的设计意图外层查询一次数据层并闭包捕获结果内层函数则针对每个页面实例每个 URL快速做布尔判断从而避免为每个页面重复执行 GraphQL 查询兼顾正确性与构建性能。2.4 典型实战按日期延迟旧文章结合 DSG 使用指南 中的真实场景博客使用gatsby-transformer-remark每篇 Markdown 的 frontmatter 含slug与date目标是延迟所有早于 2021-10-31 的文章。模板src/pages/{MarkdownRemark.frontmatter__slug}.jsximport * as React from react import { graphql } from gatsby export default function Component(props) { return pre{JSON.stringify(props, null, 2)}/pre } export const query graphql query ($id: String) { markdownRemark(id: { eq: $id }) { html frontmatter { slug date } } } export async function config() { const { data } graphql { oldPosts: allMarkdownRemark( filter: { frontmatter: { date: { lt: 2021-10-31 } } } ) { nodes { frontmatter { slug } } } } const oldPosts new Set(data.oldPosts.nodes.map(n n.frontmatter.slug)) return ({ params }) { return { defer: oldPosts.has(params.frontmatter__slug) } } }这里params.frontmatter__slug对应文件路径中的{MarkdownRemark.frontmatter__slug}动态段将当前文章的 slug 与旧文章集合比对命中则defer: true。2.5 对照gatsby-node.js中使用createPagedefer若你使用createPagesAPI而非文件系统路由DSG 的写法是在createPage中直接传defer参数参考 DSG API 参考 与 使用指南const blogPostTemplate require.resolve(./src/templates/blog-post.js) exports.createPages async ({ graphql, actions, reporter }) { const { createPage } actions const result await graphql( query { allMdx(sort: { frontmatter: { date: DESC }}) { nodes { slug } } } ) if (result.errors) { reporter.panicOnBuild(There was an error loading posts, result.errors) return } const posts result.data.allMdx.nodes posts.forEach((post, index) { createPage({ path: post.slug, component: blogPostTemplate, context: { slug: post.slug, }, // index is zero-based index defer: index 1 100, }) }) }查询结果按日期降序排列前 100 篇defer: false在构建时生成其余 900 篇defer: true延迟到首次请求。defer参数是可选的缺省表示构建时生成。2.6 测试config()的注意事项发布说明明确指出gatsby develop下 DSG 不生效目前只能通过gatsby build测试config()这是config()API 的首个迭代版本Gatsby 团队公开征集反馈本地测试延迟生成的具体方式是执行gatsby build后运行gatsby serve延迟页面会在首次请求时生成。2.7 DSG 的已知限制从 DSG API 参考 可以看到两条重要限制使用前需知悉gatsby-config中不允许使用函数配置文件会被打包进 DSG 引擎必须是可序列化的函数/回调会失效module.exports { plugins: [ { resolve: gatsby-plugin-acme, options: { // ⚠️ Doesnt work optionA: () foobar, // OK optionB: foobar } } ] }DSG 引擎不支持onCreateWebpackConfig通过该 API 修改的 webpack 配置不会应用到 DSG 引擎在gatsby-node的createResolvers/createSchemaCustomization等 API 中若依赖自定义 webpack 变更如路径别名则无法工作。三、核心特性二gatsby-config.js中的 JSX Runtime 选项3.1 新配置项v4.1 允许在gatsby-config.js中直接配置jsxRuntime与jsxImportSourcemodule.exports { jsxRuntime: automatic, jsxImportSource: emotion/react, }jsxRuntime设置为automatic后JSX 无需显式导入 React 即可使用对应 React 官方新的 JSX 转换。取值与校验规则见 packages/gatsby/src/joi-schemas/joi.ts 第 57-58 行Joi.string().valid(automatic, classic).default(classic)即仅允许automatic/classic两个取值默认值为classic兼容旧行为需手动导入 React。jsxImportSource指定 React 底层 JSX 转换所使用的包典型场景是搭配 Emotion 等 CSS-in-JS 库如示例中的emotion/react让 JSX 转换自动注入来自该包的运行时。3.2 配置如何传递到编译管线从当前仓库源码可以看到这两个配置项的实际流向配置合并层 packages/gatsby/src/utils/merge-gatsby-config.ts 第 25-26 行定义了IGatsbyConfigInput中的类型jsxRuntime?: classic | automatic、jsxImportSource?: string表明二者属于配置输入的一部分且在主题/用户配置合并时遵循该文件的合并规则。Webpack/Babel 编译层 packages/gatsby/src/utils/webpack-utils.ts 第 393-410 行JS loader 的 options 中把reactRuntime: config.jsxRuntime与reactImportSource: config.jsxImportSource传给 Babel loader进而影响 JSX 转换插件的行为此外第 828 行还会根据config.jsxRuntime automatic决定是否启用相应的 ESLint 规则例如不再强制要求导入 React 的校验。也就是说在gatsby-config.js里声明这两个顶层键后Gatsby 会自动把它们注入 Babel/ESLint 编译配置站点内的所有页面与组件统一生效无需在每个文件中手工写/** jsxRuntime automatic */之类的 pragma。四、本版本的其他改进与 Bugfix发布说明的 Notable bugfixes improvements 部分记录了 v4 时代随附的若干修复与优化影响包内容类型gatsby缓存 Query Engine 与 SSR engine使用 DSG 时以缩短构建时间性能优化gatsby将pageContext传入getServerData()功能修复gatsby-source-contentful修复downloadLocal选项不生效的问题Bugfixgatsby-plugin-image修复重渲染时的闪烁/眨眼问题修复GatsbyImage在 IE11 不显示图片Bugfixgatsby-remark-images修复设置GATSBY_EMPTY_ALT时 figure 图注的生成Bugfixgatsby-plugin-sharp在使用gatsby-plugin-image时向 sharp 传递failOnErrorBugfix文档更新 Creating a Source Plugin 指南以适配 v4 变更文档改进其中与本主题最相关的是DSG 场景下缓存 SSR engine与getServerData()获得pageContext这两项它们分别从构建速度与 SSR/DSG 数据传递两个维度完善了动态渲染能力。需要说明的是以上条目来自发布说明的历史记录当前仓库代码已在此基础上持续演进此处仅作版本事实陈述。此外发布说明还收录了大量社区贡献者约 20 人的 PR涉及gatsby-source-wordpress、gatsby-plugin-mdx、gatsby-source-faker、gatsby-remark-images等包的文档与类型修正——这些细节体现了 v4.1 作为功能落地 社区巩固版本的特点。五、快速上手清单与版本说明若要在自己的项目中体验 v4.1 的两大新特性可按以下步骤操作升级 Gatsbynpm install gatsby4.1.0发布说明同时提示想抢先体验新功能可安装gatsbynext即 4.2 及后续预发布版本。使用 DSG File System Route API确认站点使用gatsby buildgatsby serve进行测试gatsby develop下 DSG 不生效在src/pages/下的集合路由模板如{MarkdownRemark.frontmatter__slug}.jsx中导出异步config()函数外层可选查询 GraphQL内层返回{ defer: boolean }验证defer: true的页面在首次访问时才生成且后续请求命中缓存。启用自动 JSX Runtime在gatsby-config.js顶层添加jsxRuntime: automatic可选再配jsxImportSource移除组件中多余的import React from react确认构建通过注意取值必须为automatic或classic缺省为classic见 joi.ts。若使用createPages而非文件系统路由则在createPage调用中传defer: true/false参考 DSG API 参考。遵守 DSG 限制gatsby-config内不得使用函数需可序列化避免依赖onCreateWebpackConfig的定制在 DSG 引擎中生效。六、进一步阅读File System Route API 完整语法与config()参考file-system-route-api.mdDSG API 参考含限制与工作原理解释deferred-static-generation.mdDSG 实战指南createPage与文件系统路由双路线using-deferred-static-generation.mdconfig()执行流程与页面模式解析源码page-mode.tsJSX Runtime 配置的校验与编译传递源码joi.ts、merge-gatsby-config.ts、webpack-utils.ts仓库内完整示例examples/route-apiFile System Route API 各种用法的可运行 demo【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考