ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

在 Gatsby 中使用 gatsby-plugin-preact:以 Preact 替换 React 削减约 30KB 运行时体积

在 Gatsby 中使用 gatsby-plugin-preact:以 Preact 替换 React 削减约 30KB 运行时体积 在 Gatsby 中使用 gatsby-plugin-preact以 Preact 替换 React 削减约 30KB 运行时体积【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsbygatsby-plugin-preact是 Gatsby 官方仓库中为站点提供即插即用drop-inPreact 支持的核心插件只需安装三个 npm 包并在gatsby-config.js中注册插件构建产物中的 React 就会被体积更小的 Preact 及其compat兼容层替换从而在保留绝大多数 React 开发体验的同时显著减小客户端 JavaScript 体积。读完本文你将掌握该插件的安装配置、底层 webpack/Babel 替换原理、开发期 Fast Refresh 工作机制以及使用它之前必须了解的版本与生态限制。为什么要在 Gatsby 站点中引入 PreactGatsby 构建的是以 React 为运行时基础的高性能静态站点但 React 本身React ReactDOM的运行时体积并不小。Preact 是 API 与 React 兼容的轻量级 UI 库官方文档将二者的典型体积对比为约3kbgzip 压缩后对约40kb。gatsby-plugin-preact的 README.md 明确指出尽管 Preact 并未对 React 生态提供完全支持但对于 Gatsby 站点而言它是一个很有吸引力的选项——相比使用 React大约可以省下~30kb的 JavaScript。对于以首屏加载和包体积为关键指标的内容型站点这是一笔相当可观的收益。Gatsby 官方性能优化指南 improving-site-performance.md 也把考虑使用 Preact 插件列为性能优化步骤之一gatsby-plugin-preact会让站点改由 Preact 渲染从而从 bundle 中削减 35–40kb 的 JavaScript。该指南同时给出一个重要提醒这是减小包体积的高级手段在少数边缘场景下可能引发难以排查的、偶发的异常用户交互因此不建议用于 UI 逻辑复杂的站点如 SaaS 应用。安装根据 README.md 与插件的 package.json需要同时安装三个包npm install gatsby-plugin-preact preact preact-render-to-stringgatsby-plugin-preact本插件本体preactPreact 运行时包含compat、jsx-runtime等子模块preact-render-to-string用于 Gatsby 服务端渲染gatsby build阶段生成 HTML时把组件树渲染为字符串的 SSR 渲染器是 peerDependencies 中声明的必需依赖。从 package.json 可以看出插件自身的运行时依赖还包括prefresh/babel-plugin与prefresh/webpack开发期 Fast Refresh 使用以及gatsbyjs/webpack-hot-middleware/client热更新客户端这些都会随插件自动安装无需手动处理。版本兼容性重要README 中的 Note 明确要求本插件使用Preact X任何v10.0.0之前的版本都与 Gatsby v2 不兼容。从 package.json 的 peer 依赖范围看当前版本对应gatsby ^5.0.0-next、preact ^10.3.4、preact-render-to-string ^5.1.8并且engines要求 Node.js18.0.0 26。如何配置使用在 Gatsby 项目的gatsby-config.js中注册插件即可// In your gatsby-config.js module.exports { plugins: [gatsby-plugin-preact], }插件没有可配置的 options注册后它会自动接管编译链路。如果你想在插件数组中加入其他选项或与其他插件组合使用也可以写成对象形式module.exports { plugins: [ { resolve: gatsby-plugin-preact, options: {}, // 当前版本无公开可配置项 }, ], }底层原理插件到底替换了什么插件核心逻辑集中在 src/gatsby-node.js通过 Gatsby 的onCreateBabelConfig与onCreateWebpackConfig两个 API 钩子完成替换。1. webpack alias把 React 模块重定向到 Preact在 onCreateWebpackConfig 中插件通过actions.setWebpackConfig为 webpack 配置了如下resolve.alias原始模块会被替换目标模块Preact 兼容实现reactpreact/compatreact-dompreact/compatreact-dom/test-utilspreact/test-utilsreact/jsx-runtimepreact/jsx-runtimepreact/compat是 Preact 官方提供的 React 兼容层实现了React/ReactDOM的常用 API如Component、useState、useEffect、createPortal、合成事件等因此项目中已有的 React 风格代码包括 JSX、Hooks无需改动即可在 Preact 上运行。react/jsx-runtime映射到preact/jsx-runtime则是为了配合 Gatsby 使用的 JSX 自动运行时automatic runtime让 Babel 编译出的jsx()调用直接落到 Preact 实现。在设置新 alias 之前插件还会先读取当前 webpack 配置并删除已有的react与react-domaliassrc/gatsby-node.js避免与其他插件设置的 React alias 冲突保证替换是幂等且可控的。2. 框架 chunk让 Preact 进入公共 framework bundleGatsby 默认会把 React 相关库打进一个名为framework的公共 chunkcacheGroup便于跨页面复用与长缓存。插件在build-javascript与develop两个阶段用 FRAMEWORK_BUNDLES_REGEX_PREACT 替换掉该 cacheGroup 的test正则const FRAMEWORK_BUNDLES_PREACT [ preact, react, react-dom, scheduler, prop-types, ] const FRAMEWORK_BUNDLES_REGEX_PREACT new RegExp( (?!node_modules.*)[\\\\/]node_modules\\\\/})[\\\\/] )这段逻辑的关键点有两个正则采用负向断言(?!node_modules.*)用于忽略 node_modules 中的嵌套副本例如某个包自带一份 React让这些副本与其宿主issuer一起打包避免重复加载多份框架代码在原有react、react-dom、scheduler、prop-types基础上新增了preact本身确保 Preact 也进入公共框架 chunk 而不是被重复拆散。替换前后frameworkcacheGroup 的差异可以直接在插件的单元测试 src/tests/gatsby-node.js 的快照中看到替换后test变更为匹配preact|react|react-dom|scheduler|prop-types的新正则。3. SSRpreact-render-to-string 负责生成 HTMLgatsby build阶段需要把每个页面组件渲染成静态 HTML。由于 React 已被 alias 替换为 PreactGatsby 原本调用的react-dom/server渲染路径也随之落到 Preact 兼容层而 SSR 所需的字符串渲染能力由你安装的preact-render-to-string提供。这就是它被列为 peerDependency 的原因——缺少它时构建阶段将无法完成 HTML 生成。开发体验Preact 专属 Fast Refresh 与错误覆盖层Gatsby v2 开发模式默认使用 React Refresh 提供组件的热更新Fast Refresh。替换为 Preact 后React Refresh 不再适用因此插件针对开发模式做了三件事均在 src/gatsby-node.js 中完成注入 Preact 专属刷新插件实例化prefresh/webpack导出的PreactRefreshPlugin并指定overlay.module为gatsby/dist/utils/fast-refresh-module复用 Gatsby 的 Fast Refresh 覆盖层 UI移除 ReactRefreshPlugin将 webpack 插件列表中constructor.name ReactRefreshPlugin的实例过滤掉防止两套刷新机制并存冲突注入热更新客户端在entry.commons顶部插入gatsbyjs/webpack-hot-middleware/client恢复开发服务器的热更新通信。同时onCreateBabelConfig 只在develop阶段注意条件判断为stage develop测试用例也验证了develop-html阶段不会注入添加prefresh/babel-plugin用于支持 Preact Hooks 的 Fast Refresh。此外src/gatsby-browser.js 中的onClientEntry会在非生产环境下加载preact/debug提供更友好的开发期警告并执行./fast-refresh/prefreshGlueCode。这段胶水代码src/fast-refresh/prefreshGlueCode.js做了两件事通过gatsbyjs/webpack-hot-middleware/client的useCustomOverlay注册自定义错误覆盖层把ok/still-ok/warnings/errors消息桥接到__prefresh_errors__Preact Refresh 的错误面板其中编译错误会先经 src/fast-refresh/formatWebpackErrors.js 格式化该实现基于react-refresh-webpack-plugin的客户端工具可清理 webpack 头信息、剥离无用的内部堆栈、聚焦语法错误监听全局error与unhandledRejection事件把运行期错误上报到 Preact 的运行时错误面板保证开发体验与 React 时代对齐。使用注意事项与边界React 生态兼容性README 明确说明 Preact 不提供对 React 生态的完整支持。依赖 React 内部机制或react-dom特有 API 的第三方库如部分动画库、复杂状态库的 devtools 集成在 Preact 下可能表现异常接入前应对站点用到的库做冒烟验证。不适用于复杂交互站点按官方性能指南的提醒该方案更适合内容型站点对 UI 逻辑复杂如 SaaS 类应用的站点不推荐因为边缘场景下可能出现难以复现的交互异常。开发者工具切换使用 Preact 后浏览器插件需从 React Developer Tools 换成 Preact Developer Tools 才能正常检查组件行为。只影响客户端 bundle 的瘦身此插件替换的是运行时不改变 Gatsby 的数据层、GraphQL 与构建管线现有页面代码与查询逻辑无需改动。如何验证替换是否生效仓库自带的单元测试 src/tests/gatsby-node.js 覆盖了插件在开发与生产两个阶段的行为可用于理解替换的期望结果开发阶段断言prefresh/babel-plugin只注入一次develop阶段、setWebpackConfig携带preact/compat等 alias、webpack 插件列表包含PreactRefreshPlugin且entry.commons被插入gatsbyjs/webpack-hot-middleware/client生产阶段断言不会注入 Babel 刷新插件、alias 配置不变且frameworkcacheGroup 的test被替换为匹配preact|react|react-dom|scheduler|prop-types的正则。对实际站点而言最简单的验证方式是执行gatsby build后检查输出的framework-*.js公共 chunk替换成功后其中应包含 Preact 相关代码也可以对比接入插件前后gatsby build的 JavaScript 体积报告预期可见约 30–40kb 的缩减。小结gatsby-plugin-preact通过两个 API 钩子在编译层完成React → Preact的无感替换用 webpack alias 把react/react-dom/jsx-runtime重定向到preact/compat与preact/jsx-runtime用正则改写framework公共 chunk 使 Preact 进入框架包并在开发模式下以prefresh体系替换 React Refresh配合preact-render-to-string完成 SSR。它以极低的接入成本两个配置行 三个 npm 包换取约 30kb 的运行时体积收益是内容型 Gatsby 站点做包体积优化时值得认真评估的官方方案——前提是接受其生态兼容性边界与复杂交互场景下的潜在风险。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进