深入解析 @wordpress/babel-preset-default:WordPress/Gutenberg 官方 Babel 预设的配置、扩展与 Polyfill 机制
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
本文围绕 Gutenberg 仓库中的@wordpress/babel-preset-default展开,系统讲解这一官方 Babel 预设的安装、使用、扩展配置与 Polyfill 机制。读者在阅读后将掌握如何在 WordPress 插件、Gutenberg 扩展或任意 npm 项目中使用该预设,理解它内置的 ECMAScript 语言特性与 JSX/TypeScript 支持范围,并学会通过wp:polyfill魔法注释与build/polyfill.js完成浏览器兼容层的接入。
一、预设是什么:为 WordPress 开发定制的默认 Babel 配置
@wordpress/babel-preset-default是 WordPress 官方提供的默认 Babel 预设,属于 Gutenberg monorepo 中的一个独立 npm 包(版本 8.55.0,见 package.json)。它的职责是:当你的代码需要被 WordPress 生态(包括 Gutenberg 编辑器本身、插件、主题)运行时,由它统一决定哪些语言特性可以被转换、如何转换、以及如何注入运行时辅助代码。
它覆盖两类语法来源:
- ECMAScript 提案:仅支持已进入 TC39 Stage 4("Finished") 中的相关章节)。
- JSX 语法扩展:通过
@babel/plugin-transform-react-jsx以runtime: 'automatic'模式转换,无需手动引入React即可使用新的 JSX 转换。
从源码看预设的实际组成
查看预设的入口实现 index.js,可以看到最终输出的配置结构:
return { presets: [ getPresetEnv(), require.resolve( '@babel/preset-typescript' ), ], plugins: [ require.resolve( '@babel/plugin-syntax-import-attributes' ), require.resolve( '@wordpress/warning/babel-plugin' ), [ require.resolve( '@babel/plugin-transform-react-jsx' ), { runtime: 'automatic' } ], maybeGetPluginTransformRuntime(), wpBuildOpts.addPolyfillComments && replacePolyfills, ].filter( Boolean ), };也就是说,除@babel/preset-env外,该预设还默认开启:
- TypeScript 支持:内置
@babel/preset-typescript,因此.ts/.tsx文件可以直接编译(类型检查仍由 tsc 负责,Babel 只做语法剥离)。 - Import Attributes:通过
@babel/plugin-syntax-import-attributes支持import data from './x.json' with { type: 'json' }这类语法。 - JSX 自动运行时:采用
runtime: 'automatic',编译产物引用react/jsx-runtime,无需在源码中显式import React。 - WordPress 警告插件:
@wordpress/warning/babel-plugin会在生产构建时移除warning()调用。
二、安装与使用:三条命令接入官方预设
安装
预设本身只负责配置,实际转换仍由@babel/core完成(该预设将其声明为依赖,见 package.json)。在项目根目录执行:
npm install @wordpress/babel-preset-default --save-dev注意:该包要求长期支持(LTS)状态的 Node.js 版本(engines字段声明为node >=18.12.0、npm >=8.19.2,见 package.json),不兼容旧版本 Node。
在 Babel 配置中启用
Babel 支持多种配置方式(.babelrc、babel.config.js、package.json中的babel字段等),核心做法是把预设名放入presets数组。使用.babelrc的示例:
{ "presets": [ "@wordpress/babel-preset-default" ] }三、预设内部逻辑:按环境自动选择 targets
从源码可以看到,该预设是一个函数式配置(module.exports = ( api ) => {...}),它会根据api.env()与api.caller()动态决定编译目标:
- 测试环境(
envName为test):targets固定为{ node: 'current' },且modules保持默认(可被 Node 直接执行),并跳过@babel/plugin-transform-runtime(见 index.js 中isTestEnv分支)。 - 生产/构建环境:
modules: false(保留 ES Module 供打包器 tree-shaking),targets优先读取项目根目录的browserslist配置,若无则回退到@wordpress/browserslist-config定义的默认浏览器矩阵:
'> 1%', 'last 1 Android versions', 'last 1 ChromeAndroid versions', 'last 2 Chrome versions', 'last 2 Firefox versions', 'last 2 Safari versions', 'last 2 iOS versions', 'last 2 Edge versions', 'last 2 Opera versions',这正好对应 WordPress 项目支持的浏览器基线,也是build/polyfill.js选择 polyfill 条目的依据。
- Gutenberg 官方构建(caller 名为
WP_BUILD_MAIN/WP_BUILD_MODULE时):会读取 caller 传入的modules、useESModules、addPolyfillComments等选项,实现主入口与 ESM 模块产物的差异化输出。
此外,@babel/preset-env开启了bugfixes: true,让 Babel 只做"最小必要"的语法转换,减少多余输出。
四、扩展配置:在官方预设之上叠加插件
该预设是一份"有主见"(opinionated)的配置。若想增加或覆盖其行为,只需要在自身 Babel 配置的plugins/presets中追加插件——Babel 保证plugins先于presets执行,因此追加的插件可以覆盖预设内置的同名转换。
例如,某个 Stage 3 提案特性尚未被 WordPress 采纳,但你的项目确实需要,可以显式加入对应插件:
{ "presets": [ "@wordpress/babel-preset-default" ], "plugins": [ "@babel/plugin-transform-class-properties" ] }需要精确了解默认启用了哪些插件时,可直接阅读预设实现 packages/babel-preset-default/index.js 中的presets与plugins数组。
五、Polyfill 机制:build/polyfill.js与wp:polyfill魔法注释
5.1 独立的 Polyfill 文件
该包提供一个配套的build/polyfill.js(压缩版build/polyfill.min.js),用于补齐 WordPress 支持浏览器中缺失的 ECMAScript 特性(参考 WordPress 官方浏览器支持政策;引入于 PR #31279)。
它的定位是:
- 作为已废弃的
@babel/polyfill包的直接替代品(drop-in replacement); - 底层基于
core-js构建(core-js同时是该包依赖,见 package.json); - 通过构建脚本 bin/index.js 生成:先产出
build/polyfill.js,再经 terser 压缩为build/polyfill.min.js。
使用方式有两种:把 polyfill 内容前置拼接到编译后的代码之前,或作为一个独立的<script>在业务代码之前加载:
<script src="path/to/polyfill.min.js"></script> <script src="path/to/your-bundle.js"></script>注意:polyfill 只覆盖已进入 Stage 4 的特性。若你使用了尚未定稿的 TC39 提案(非 Stage 4),该 polyfill 不会自动导入对应补丁,你需要自行从core-js等方案按需引入。
5.2 按需注入与wp:polyfill魔法注释
预设内部有一个自定义 Babel 插件 replace-polyfills.js:它遍历代码中所有import 'core-js/...'与require( 'core-js/...' )语句,将其删除,并在文件顶部写入一条魔法注释/* wp:polyfill */,标记该文件依赖全局 polyfill:
// 编译前 import 'core-js/stable/array/flat-map'; // 编译后 /* wp:polyfill */这一机制在 Gutenberg 官方构建(caller 提供addPolyfillComments: true时,配合@babel/preset-env的useBuiltIns: 'usage')下生效,让打包器能据此把文件归属到依赖wp-polyfill的资源清单中,避免重复注入。
5.3 刻意排除的 polyfill 清单
polyfill-exclusions.js 定义了一组被刻意排除的 polyfill:
| 排除项 | 原因 |
|---|---|
es.array.push | 规避非可写数组(non-writable arrays)相关的 Chromium 罕见 bug(见 Chromium issue 42202623) |
web.immediate | IE 专属特性,WordPress 不使用也不希望为其补丁(见 PR #49234) |
/^es(next)?\.set\./ | Babel/core-js 会对所有new Set()无差别注入全部实例方法 polyfill,造成不必要的体积与性能开销,因此整体关闭(见 PR #67230) |
/^es(next)?\.iterator\./ | 与 Set 同理,排除全部 iterator helper polyfill |
其中 Set 与 Iterator 需要同时以es.与esnext.前缀声明,这是 Babel/core-js 内部依赖关系的特殊性决定的。开发者在面向旧浏览器时需自行确保不使用这些特性。
六、测试与验证:预设行为有据可查
该包使用 Vitest 编写测试(见 test/index.js),覆盖两类场景:
- 基础转译:以 fixtures/input.js 为输入(包含 async generator 函数、可选链
obj?.foo?.bar等现代语法),在envName: 'production'下转译并与快照对比,验证 Stage 4 特性被正确保留/转换(快照见 index.js.snap)。 - 魔法注释注入:以 fixtures/polyfill.js(内部使用
Promise.try这类需要 polyfill 的特性)为输入,传入caller: { name: 'WP_BUILD_MAIN', addPolyfillComments: true },断言输出包含/* wp:polyfill */注释。
这为"预设确实启用了哪些特性、polyfill 标记如何产生"提供了可运行、可复现的验证入口。
七、小结与适用场景
@wordpress/babel-preset-default的价值在于把 WordPress 的语法与兼容策略收敛为一套可复用的官方配置:生产构建保持 ESM、测试环境针对当前 Node、JSX 自动运行时开箱即用、TypeScript 语法直接支持,同时通过build/polyfill.js与wp:polyfill注释建立了与 Gutenberg 构建流水线一致的 polyfill 分工。
适用场景包括:
- WordPress 插件/主题使用现代 JavaScript 或 JSX 开发,希望遵循官方编译标准;
- 在 Gutenberg 生态中开发独立包,需要与官方构建产物保持一致的转译口径;
- 需要替代已废弃的
@babel/polyfill,获得一个基于core-js、面向 WordPress 浏览器基线的即用 polyfill。
若需深度定制,建议以 index.js 为蓝本,结合自身browserslist配置与 Babel 插件优先级,在项目级配置中逐步叠加或覆盖。
【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考