
Cypress cypress/webpack-batteries-included-preprocessor 深度解析开箱即用的 Webpack 测试文件预处理方案【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress本篇基于 Cypress 仓库中npm/webpack-batteries-included-preprocessor包的 README 及其源码实现展开系统讲解这个电池全含batteries included预处理器的定位、安装与配置方式、TypeScript 支持与 Node 内置模块 shim 机制并结合 index.ts 的源码与测试用例还原它在 webpack 打包链路中的真实工作原理帮助你在 Cypress 项目中快速启用并排错 JS/TS 测试文件预处理。为什么需要这个预处理器与 cypress/webpack-preprocessor 的关系Cypress 默认将.js测试文件原样加载到浏览器中无法处理 ES 模块语法、TypeScript、JSX 等需要编译的特性。为此 Cypress 提供了file:preprocessor钩子允许你在文件加载前用任意工具通常是 Webpack对测试文件进行打包编译。cypress/webpack-batteries-included-preprocessor的定位可以从 npm/webpack-preprocessor/README.md 的对比中看出它本质上是 cypress/webpack-preprocessor 的一个封装层wrapper。二者的分工是cypress/webpack-preprocessor基础预处理器不包含babel-loader、ts-loader等额外依赖因为大多数用户会带上自己的webpack.config.js并已在项目中装好所需 loader。cypress/webpack-batteries-included-preprocessor面向不想自己配置的用户把 Babel、TypeScript 支持、Node 内置模块 polyfill 等全部依赖内置开箱即用。从 AGENTS.md 的架构说明可以印证这一设计包内直接依赖并打包了大量babel/*、ts-loader等库目的就是让消费者consumer无需自行安装这些依赖。这正是两个预处理器配置自由度与开箱即用两种取舍的体现。安装与版本选型按照 README安装该包时必须同时安装其被封装的底层包这样才能独立升级底层版本npm install --save-dev cypress/webpack-batteries-included-preprocessor cypress/webpack-preprocessor版本与 webpack 大版本的对应关系README 明确说明webpack 版本预处理器版本线webpack v5cypress/webpack-batteries-included-preprocessor3.x.x及以上webpack v4cypress/webpack-batteries-included-preprocessor2.x.x从 CHANGELOG.md 可以看到版本演进的脉络v3.0.02023-08对齐 Cypress 改用 webpack v5最低 webpack 版本提升至 5v4.0.02025-08移除 webpack 4 支持并精简内置 Node 内置模块 shimv4.1.0TypeScript 6 兼容v4.2.0支持 TypeScript 7 的 spec 预处理v5.0.0移除内置 CoffeeScript 支持coffee-loader与coffeescript依赖被删除CoffeeScript spec 需要改用自定义 webpack 配置的cypress/webpack-preprocessor自行处理。同时 package.json 将cypress/webpack-preprocessor^6.0.4声明为peerDependency即两个包必须成对安装源码层面index.ts直接import webpackPreprocessor from cypress/webpack-preprocessor并将其作为最终执行者。基本用法在 cypress.config.js 中注册最简用法是把预处理器的返回值挂到file:preprocessor钩子上README 的 Usage 章节const webpackPreprocessor require(cypress/webpack-batteries-included-preprocessor) module.exports (on) { on(file:preprocessor, webpackPreprocessor()) }从源码看index.ts#L305-L323webpackPreprocessor(options)返回的是一个接收file事件对象含filePath/outputPath的回调其执行流程为若文件扩展名匹配/\.m?tsx?$/但未配置typescript选项直接 reject 并提示安装 typescript对应 e2e 测试中未配置 typescript 时处理 .ts/.tsx 报错的用例见 features.spec.ts若未提供webpackOptions自动填充默认 Webpack 配置getDefaultWebpackOptions()若配置了typescript调用addTypeScriptConfig()动态注入 TypeScript 相关规则最终把选项透传给webpackPreprocessor(options)(file)完成真正的 webpack 编译。启用 TypeScript 支持README 说明需先安装 TypeScriptnpm install --save-dev typescript再通过typescript选项传入其位置const webpackPreprocessor require(cypress/webpack-batteries-included-preprocessor) module.exports (on) { on(file:preprocessor, webpackPreprocessor({ typescript: require.resolve(typescript) })) }typescript选项在源码中支持string | boolean两种形态index.ts#L80-L113传字符串路径如require.resolve(typescript)直接使用你指定的 TypeScript 编译器传true从你的tsconfig.json所在目录向上解析require.resolve(typescript, { paths: [configFileDirectory] }这也是 4.0.2 版本correctly discover TypeScript compiler修复的行为。无论哪种方式解析失败都会抛出TypeScriptNotFoundError若 TS 文件在目录层级中找不到tsconfig.json则抛出TsConfigNotFoundError提示在项目根或 cypress 目录添加tsconfig.json这两条错误路径在 test/unit/index.spec.ts 中都有对应断言。源码视角TypeScript 规则是如何被注入的addTypeScriptConfig()index.ts#L80-L210会根据解析到的 TypeScript 版本走不同分支这是理解该预处理器行为的关键TypeScript 7走 ts-loader// 简化自 index.ts webpackOptions.module.rules.push({ test: /\.m?tsx?$/, exclude: [/node_modules/], use: [{ loader: require.resolve(ts-loader), options: { // TS 6只传 configFile让 ts-loader 自行读文件 // TS 6显式转发 tsconfig 的 compilerOptions compiler: typeScriptPath, logLevel: error, silent: true, transpileOnly: true, }, }], })细节上有几个值得注意的兼容处理均有对应单测佐证TS 6把用户 tsconfig 的compilerOptions显式转发给 ts-loader且不传configFileconfigFile仅在 TS 6 传递测试见 index.spec.ts#L206-L275moduleResolution: node10会被改写为node因为 tsx 将两者都解析为 node10而 ts-loader 对 node10 的校验在不同 TS 版本下表现不稳定测试见 index.spec.ts#L120-L147已存在 ts-loader 时不重复添加hasTsLoader()用正则/(^|[^a-zA-Z])ts-loader([^a-zA-Z]|$)/检查已有 rules避免误报与重复注入4.0.1 修复的正是 ts-loader 检测的误报问题。TypeScript 7走 Babel 转译TypeScript 7 不再提供 JavaScript 编译器 APIts-loader 会崩溃因此源码改用babel-loaderbabel/preset-typescript完成转译index.ts#L143-L155并保持与 ts-loader 的行为对齐依次挂载babel-plugin-transform-typescript-metadata与babel/plugin-proposal-decoratorsversion: legacy顺序上 metadata 必须在前以维持emitDecoratorMetadata的产出一致e2e 测试中的 typescript_decorators_spec.ts 用例专门验证 TS 7 下装饰器元数据仍能正确产出。所有 TS 版本共享的解析配置webpackOptions.resolve.extensions webpackOptions.resolve.extensions.concat([.ts, .tsx]) webpackOptions.resolve.extensionAlias webpackOptions.resolve.extensionAlias || { .js: [.ts, .js], .mjs: [.mts, .mjs], } // 仅在确实找到 tsconfig.json 时注册 paths 插件 webpackOptions.resolve.plugins [new TsconfigPathsPlugin({ configFile: configFile.path, silent: true })]这里体现了对 tsconfigpaths路径别名的支持TS 6 使用tsconfig-paths-webpack-plugin-v3别名映射TS 6 使用 v4 版本以兼容无baseUrl的 paths新写法4.1.1 的修复e2e 用例 paths-no-baseurl/spec.ts 验证了这一点。源码注释还特别说明了为何必须找到 tsconfig 才注册插件v4 插件在loadConfig失败时不再提前返回传 undefined 的 configFile 会导致其从process.cwd()向上回溯并在 resolve 阶段崩溃。extensionAlias的作用是让import ./foo、import ./foo.mjs这类省略扩展名的导入能优先解析到.ts/.mts源文件这正是 3.1.2 版本Add extensionAlias for ESM TS修复的能力。默认 Webpack 配置ES 特性、JSX 与 Node shim不传webpackOptions时预处理器使用getDefaultWebpackOptions()index.ts#L212-L303生成的完整配置。其核心构成1. Babel 规则与 ES 特性支持module: { rules: [{ test: /\.mjs$/, include: /node_modules/, // 第三方 .mjs 走宽松解析 exclude: [/browserslist/], type: javascript/auto, }, { test: /(\.jsx?|\.mjs)$/, exclude: [/node_modules/, /browserslist/], type: javascript/auto, use: [{ loader: require.resolve(babel-loader), options: getBabelLoaderOptions() }], }], }getBabelLoaderOptions()index.ts#L38-L68是支持各种 proposal 阶段 ES 特性的具体实现插件babel-plugin-add-module-exportsES/CJS 互操作的关键、babel/plugin-transform-class-properties、babel/plugin-transform-object-rest-spread、babel/plugin-transform-runtime运行时以absoluteRuntime指向预处理器自带的babel/runtime预设babel/preset-envmodules: commonjs目标浏览器为Chrome 64源码注释要求与packages/web-config/webpack.config.base.ts及packages/server/lib/browsers/chrome.ts中的 Chrome 版本保持同步、babel/preset-reactJSX 支持configFile: false, babelrc: false显式禁用用户项目中的 babel 配置文件。2.2.2 版本即有Disable loading babel config files的修复目的是保证不同项目里预处理器行为一致避免用户项目里不相关的 babel 配置污染编译。2. 全局注入node选项与 ProvidePluginnode: { global: true, __filename: true, __dirname: true }, plugins: [new webpack.ProvidePlugin({ Buffer: [buffer, Buffer], process: require.resolve(process/browser.js), })]这解释了测试夹具 node_shim_spec.js 为何能断言typeof global object、__filename/__dirname存在——webpack 的node选项在浏览器端模拟了这些 Node 全局。process的解析特意指向预处理器包内安装的process/browser.js源码注释说明这是为了规避 PnP/Yarn 场景下用户node_modules中可能没有该包的解析问题。3.resolve.fallback内置模块 shim 的完整清单resolve.fallback决定了哪些 Node 内置模块在浏览器端可用。当前默认配置中真正提供 shim 的只有五个内置模块替代实现bufferbuffer包osos-browserify/browserpathpath-browserifyprocessprocess/browser.jsstreamstream-browserify其余如fs、crypto、http、zlib、dns等全部显式置为false即禁用。这与 README 的说法完全一致自4.x.x起cypress/webpack-batteries-included-preprocessor只包含buffer、path、process、os、stream这五个内置模块的 shim4.0.0 的 breaking change 正是移除了其余 shim。缺少其他内置模块时getFullWebpackOptions()如果项目代码import zlib from zlibREADME 给出的标准解法是取出预处理器默认配置再装饰它const webpackPreprocessor require(cypress/webpack-batteries-included-preprocessor) function getWebpackOptions () { const options webpackPreprocessor.getFullWebpackOptions() // add built-ins as needed options.resolve.fallback.zlib require.resolve(browserify-zlib) return options } module.exports (on) { on(file:preprocessor, webpackPreprocessor({ webpackOptions: getWebpackOptions() })) }getFullWebpackOptions(filePath?, typescript?)在源码中的实现index.ts#L330-L338即生成一份新的默认配置若同时给出文件路径与 typescript 选项还会把 TypeScript 规则一并合并进去供你检查或二次加工完整的 webpack 选项。resolve.fallback的语义false禁用、模块名字符串映射到 polyfill参见 webpack 官方文档resolve.fallback一节。除typescript与webpackOptions之外该预处理器支持的其余选项与 cypress/webpack-preprocessor 完全相同README 原话例如watch、compiler相关行为等均可参阅其 README。此外源码还挂了一个preprocessor.defaultOptionsindex.ts#L325-L328即{ webpackOptions: getDefaultWebpackOptions(), watchOptions: {} }e2e 测试验证了基于defaultOptions展开时 TypeScript 支持仍会在处理后自动补齐因为defaultOptions中并不预置 TS 配置它依赖每个文件的处理流程动态添加。调试使用 webpack-bundle-analyzer 定位 chunk / 体积问题README 的 Debugging 章节给出了一条官方推荐的排障路径当遇到chunk load 错误或** bundle 体积异常**尤其出现在端到端测试中时启动 Cypress 前设置export DEBUGcypress-verbose:webpack-batteries-included-preprocessor:bundle-analyzer源码中对应实现index.ts#L11 与 index.ts#L255-L258当该 debug 命名空间被Debug.enabled()命中时默认 webpack 插件列表会追加一个BundleAnalyzerPlugin生成可视化报告。该插件分析的是 support filecypress open时首次打包与各个 spec 文件后续打包的构成可帮助判断是哪个依赖把 bundle 撑大或导致 chunk 加载失败。README 还建议向 Cypress 提 issue 时附上这份报告便于官方定位。webpack-bundle-analyzer4.10.2是该包的固定依赖见 package.json因此无需额外安装。能力边界一览测试用例映射到功能承诺e2e 测试文件 test/e2e/features.spec.ts 把 README 宣称的各项能力逐一变成了可运行验证可作为该预处理器到底支持什么的权威清单ES 特性与互操作es_features_spec.js覆盖 CJS/ESM 互操作、对象展开、类属性、async/awaitJSXjsx_spec.jsx.mjsESM 文件mjs_spec.mjs导入.js/.json/.jsx/.mjsvarious_imports_spec.jsNode 全局 shimnode_shim_spec.jsglobal、__filename、__dirname内联 source map输出包含//# sourceMappingURLdata:application/json...base64默认开启 source map3.0.6 修复调整了该项默认值;TypeScript 全形态.ts/.tsx编译、tsconfigpaths别名含无baseUrl的 TS6 写法、ESM.ts/.mts导入、esModuleInterop为true/false两种形态、TS 7 下经 Babel 转译且装饰器元数据保持对齐错误路径未配置typescript选项时处理.ts/.tsx会报明确错误。单元测试 test/unit/index.spec.ts 则聚焦配置注入逻辑本身tsconfigcompilerOptions是否正确转发给 ts-loader、moduleResolution: node10 → node的改写、TS 5/6/7 各版本分支、BundleAnalyzerPlugin 在 debug 开启时的挂载等上文源码视角各小节的结论均可在此找到断言依据。在仓库中运行该包的测试按照 README 与 AGENTS.md贡献者应使用与 Cypress 版本匹配的 Node仓库根部的 Node 版本文件常用命令yarn build # tsc产物输出到 dist/npm 发布的是 dist/* yarn check-ts # tsc --noEmit 类型检查 yarn lint # ESLint yarn test # vitest run yarn test -- path-to-spec # 运行指定 spec yarn test -- glob-pattern # 按 glob 运行该包以 MIT 许可发布见 LICENSE.md采用 semantic-release 自动发版README 尾部的 semantic-release 徽章与 CHANGELOG.md 的自动生成条目即为佐证。小结与选型建议综合 README 与源码实现可以归纳出该预处理器的适用画像选型如果你已有完整的webpack.config.js自配 babel/ts loader直接用更底层的 cypress/webpack-preprocessor 并传入自定义配置即可如果希望零配置跑通 ES 提案特性、JSX、.mjs、TypeScript含 paths 别名、esModuleInterop两种形态、TS 6/7 兼容cypress/webpack-batteries-included-preprocessor是官方给出的电池全含方案限制默认仅 shimbuffer/path/process/os/stream五个内置模块CoffeeScript 支持已在 v5 移除其他内置模块需通过getFullWebpackOptions()自行补充resolve.fallback排障chunk 加载失败或体积异常时优先开DEBUGcypress-verbose:webpack-batteries-included-preprocessor:bundle-analyzer拿 bundle-analyzer 报告升级两个包成对安装peerDependency关注 CHANGELOG 中各 minor 版本针对 TypeScript 大版本兼容的修复TS6 的configFile传递方式、TS7 的 Babel 转译路径是最近几个版本的核心演进。【免费下载链接】cypressFast, easy and reliable testing for anything that runs in a browser.项目地址: https://gitcode.com/GitHub_Trending/cy/cypress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考