umi 的 utoopack 打包器实战通过 extraBabelPlugins 运行 babel-plugin-istanbul 生成覆盖率标记【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi本篇技术指南基于 umi 仓库中的示例项目with-utoopack-istanbul讲解在umijs/bundler-utoopack打包器下如何让 Umi 的extraBabelPlugins配置真正生效并运行第三方 Babel 插件以babel-plugin-istanbul为例。读完后你能掌握如何在 umi 配置中开启utoopack.babelLoader、构建产物中 Istanbul 覆盖率标记__coverage__、statementMap、fnMap、branchMap的验证方法以及从源码层面理解 babel-loader 规则注入的触发条件与生效范围。示例要解决的问题utoopack 是 umi 引入的新一代打包器。与 webpack 方案相比utoopack 默认使用 Rust 原生的 SWC 系转换链路并不一定走 Babel。这就带来一个实际问题用户在 umi 配置里通过extraBabelPlugins声明的 Babel 插件例如用于注入覆盖率统计的babel-plugin-istanbul在 utoopack 打包链路下未必会被执行。该示例见 README正是为验证这一点而设计的它演示umijs/bundler-utoopack如何从 Umi 的extraBabelPlugins配置中取出 Babel 插件并在构建中运行。核心配置如下export default defineConfig({ utoopack: { babelLoader: true, }, extraBabelPlugins: [babel-plugin-istanbul], });这里两个配置项缺一不可utoopack.babelLoader: true显式开启 utoopack 链路中的 babel-loader 规则注入extraBabelPlugins: [babel-plugin-istanbul]声明要追加的 Babel 插件。示例工程结构与实际运行示例工程非常精简位于 examples/with-utoopack-istanbul包含一个页面和一份 package.json{ name: example/with-utoopack-istanbul, private: true, scripts: { build: umi build, dev: umi dev, preview: umi preview, setup: umi setup, start: npm run dev }, dependencies: { umi: workspace:* }, devDependencies: { babel-plugin-istanbul: ^6.1.1 } }注意babel-plugin-istanbul是作为devDependencies引入的它只在构建时被 Babel 加载不会进入运行时代码。页面源码 src/pages/index.tsx 中放了一个带分支逻辑的函数用于让 Istanbul 插件生成有意义的语句/函数/分支映射function getCoverageText(count: number) { if (count 0) { return ISTANBUL_PLUGIN_SOURCE_EXECUTED; } return ISTANBUL_PLUGIN_SOURCE_NOT_EXECUTED; } export default function HomePage() { const coverageText getCoverageText(1); return ( main h1Utoopack extraBabelPlugins/h1 p babel-plugin-istanbul status:{ } strong>pnpm --filter example/with-utoopack-istanbul build构建完成后检查生成的dist目录下的 chunk 文件应能搜到 Istanbul 覆盖率标记例如__coverage__、statementMap、fnMap、branchMap。这些标记是babel-plugin-istanbul注入的覆盖计数元数据它们的出现即证明插件确实在 utoopack 构建链路中执行过了。源码解析babel-loader 规则何时被注入要理解示例为什么必须写utoopack.babelLoader: true需要看 utoopack 打包器的配置生成逻辑。触发条件shouldAddBabelLoaderRules在 config.ts 中function shouldAddBabelLoaderRules(config: Recordstring, any) { return ( config.utoopack?.babelLoader true || isReactCompilerEnabled(config) ); }从源码结构看只有两种情况会在 utoopack 链路中注入 babel-loader 规则用户显式配置utoopack.babelLoader true本示例走的路径启用了 React Compiler配置中存在reactCompiler且不为false或存在forget配置见同文件中的isReactCompilerEnabled。也就是说在 utoopack 打包器下仅配置extraBabelPlugins而不开启babelLoader时默认不会为这些插件追加 babel-loader 规则。babelLoader字段本身就是umijs/bundler-utoopack的用户配置类型之一定义在 types.ts 的IUtoopackUserConfig中export type IUtoopackUserConfig ConfigComplete { babelLoader?: boolean; root?: string; watch?: IUtoopackWatchConfig; };规则内容getExtraBabelModuleRules当条件满足后config.ts 的getExtraBabelModuleRules负责构造实际的 loader 规则几个关键细节值得注意插件来源与过滤。最终生效的插件列表由三处合并而成见getExtraBabelPlugins内部注入的beforeBabelPlugins、opts 传入的extraBabelPlugins、以及用户配置里的config.extraBabelPlugins。合并后还会做两步过滤通过isSerializableBabelItem丢弃不可序列化的条目内部用JSON.parse(JSON.stringify(...))对比判断因为 utoopack 的配置需要可序列化地传递给编译进程剔除babel-plugin-import/import和 emotion 系插件——它们分别改由 utoopack 原生的optimization.modularizeImports和styles.emotion能力处理不需要经过 Babel。空规则短路。过滤后如果没有任何插件也没有额外 preset函数直接返回空对象即完全不追加规则避免无谓的 babel-loader 开销。生效范围限定。每条规则都带条件condition: { all: [ { not: foreign }, { not: { path: /[\\/]src[\\/]\.umi(?:-[^\\/]*)?[\\/]/, }, }, ], },即只对非 foreign 模块可理解为项目自身代码生效且排除src/.umi临时目录。这与示例的验证目标一致——Istanbul 标记应出现在业务页面代码对应的 chunk 中而不是依赖库或 umi 生成的运行时代码里。loader 选项。babel-loader 复用的是 webpack 打包器中预编译打包好的 babel-loaderrequire.resolve(umijs/bundler-webpack/compiled/babel-loader)选项为{ sourceType: unambiguous, babelrc: false, configFile: false, cacheDirectory: false, browserslistConfigFile: false, targets: opts.config.targets, customize: opts.config.babelLoaderCustomize, presets, // babelPreset extraBabelPresets plugins, // 过滤后的 extraBabelPlugins }规则会应用到js、mjs、cjs、jsx、ts、tsx六种扩展名上因此示例中的.tsx页面文件自然会被 babel-plugin-istanbul 处理。规则挂载位置。生产构建入口getProdUtooPackConfigconfig.ts在合并配置时把getExtraBabelModuleRules(opts)的结果并入最终 utooBundlerOpts 的config中从而让 babel-loader 规则成为 utoopack 模块规则的一部分。单元测试印证行为边界上述行为在 config.test.ts 的utoopack extra babel config测试组中有对应断言可以对照阅读adds babel-loader rules for extraBabelPlugins in production开启babelLoader: true后生产配置中应出现babel-loader规则选项包含babelrc: false等且plugins中保留了形如[babel-plugin-istanbul, { cwd: /tmp }]的插件及其选项does not add babel-loader rules unless utoopack babelLoader is enabled未开启babelLoader时即使配置了babel-plugin-istanbul等插件也不会追加 babel-loader 规则keeps native babel plugin adapters when babelLoader is enabled开启后原生适配的插件如babel-plugin-import、emotion/babel-plugin仍走 utoopack 原生能力plugins中只留下babel-plugin-istanbul这类需要真正经 Babel 执行的插件。测试用例直接以babel-plugin-istanbul作为测试对象与本示例的验证目标一致。验证构建产物构建完成后验证方式分两层静态验证在dist目录下全文搜索__coverage__、statementMap、fnMap、branchMap。这些标记出现在打包 chunk 中说明babel-plugin-istanbul在 utoopack 构建链中真实执行并注入了覆盖率元数据。运行验证如需要运行npm run dev/npm run preview后页面中的strong contenteditable="false">【免费下载链接】umiA framework in react community ✨项目地址: https://gitcode.com/GitHub_Trending/um/umi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考