Vue CLI 默认 Babel 预设 vue/babel-preset-app 完整解析特性、选项与浏览器兼容实战【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-clivue/babel-preset-app 是 Vue CLI 所有新建项目的默认 Babel 预设它把babel/preset-env、Vue JSX 支持、Stage 3 及以下提案插件和babel/plugin-transform-runtime整合成一套开箱即用的配置并基于 browserslist 目标自动决定语法转译与 polyfill 注入。本文围绕该预设的设计定位、内置特性、全部可配置项及依赖 polyfill 的三种处理方案展开结合仓库源码与测试用例深入说明其底层机制帮助你在 Vue CLI 项目中精确控制转译行为、诊断第三方依赖的兼容性问题。定位与使用前提根据 packages/vue/babel-preset-app/README.md 的说明这个预设只面向 Vue CLI 创建的项目使用不承诺支持外部独立使用场景。在 Vue CLI 项目中它通常以vue/cli-plugin-babel/preset的形式被引用该入口文件 preset.js 仅是require(vue/babel-preset-app)的一行转发新版项目默认生成的babel.config.js大致如下module.exports { presets: [ vue/cli-plugin-babel/preset ] }从 package.json 可以看到它声明了对babel/core、babel/preset-env、core-jsv3与vue^2 || ^3.2.13的 peer 依赖其中core-js和vue均为可选——也就是说在纯 Node 测试环境或未安装 Vue 的场景下预设依然可以工作。需要特别留意的一点是历史命名早期 Vue CLI 项目使用vue/app预设名迁移脚本 usePluginPreset.js 会把babel.config.js中的vue/app与vue/babel-preset-app字面量自动改写为vue/cli-plugin-babel/preset避免在升级过程中手工修改。内置特性总览该预设的核心组装逻辑位于 index.js返回的 Babel 配置同时包含多个 preset 与 plugin下面按 README 的章节逐一说明。1. babel/preset-env按浏览器目标自动转译与补全babel/preset-env会根据浏览器目标自动决定需要应用的转译规则和 polyfill是整个预设的基石。预设对其施加了以下默认行为modules: false保留 ES Module 语法交给 webpack 处理以支持 tree-shaking在 Jest 测试中会自动切换为commonjs。useBuiltIns: usage基于源码中的实际用法按需注入 polyfill详见下文。targets默认读取项目的 browserslist 配置推荐放在package.json的browserslist字段中除非显式传入targets或ignoreBrowserslistConfig选项在 Node.js 环境运行单元测试时强制为{ node: current }。默认包含Promisepolyfill即使某些依赖未经 Babel 转译也能在需要的环境中直接使用 Promise。源码 index.js 中组装给 preset-env 的envOptions还包含bugfixes: true、corejs读取已安装 core-js 的版本号仅在使用useBuiltIns时传入等细化配置并将前面计算出的 polyfill 列表合并进exclude避免 preset-env 与预设自带的 polyfill 重复注入。测试环境自动识别当NODE_ENV testJest 与 Mocha 都会设置且非VUE_CLI_TEST时index.js 会设置两个环境变量VUE_CLI_BABEL_TARGET_NODE true随后 targets 被强制为{ node: current }VUE_CLI_BABEL_TRANSPILE_MODULES true将modules切换为commonjs并追加babel-plugin-dynamic-import-node保证 Jest 不打包环境下的动态import()也能正常工作。2. Stage 3 及以下提案特性该预设只内置支持以下三种未进入正式标准的语法对象 rest/spread 已作为 preset-env 的一部分被支持不在此列Dynamic Import 语法动态import()经babel/plugin-syntax-dynamic-import支持参见 index.jsClass Properties 提案babel/plugin-proposal-class-properties其loose选项跟随预设的loose选项Decorators 提案legacy 模式babel/plugin-proposal-decorators默认legacy为 true可通过decoratorsLegacy关闭。如果项目还需要其他 Stage 3 或更低阶段的特性README 明确要求自行安装并配置对应插件——这是 Babel 7 移除 Stage preset 之后的保守默认策略。3. Vue JSX 支持预设内置了 JSX 语法支持并会根据项目中实际安装的 Vue 版本自动选择转译实现见 index.jsVue 2 项目使用vue/babel-preset-jsxVue 3 项目使用vue/babel-plugin-jsx。这一分支判断通过require(vue)读取Vue.version的主版本号完成如果项目未安装 Vue则回退到 Vue 2 的 JSX 预设。测试用例 babel-preset.spec.js 中的jsx用例验证了默认注入h的行为jsx options用例则验证了传入{ injectH: false }时可以关闭自动注入。4. babel/plugin-transform-runtime仅抽取 helpers预设启用了babel/plugin-transform-runtime作用是避免在每个文件里内联 Babel 辅助函数如_objectSpread统一从babel/runtime引入显著减小代码体积。它的注入策略index.js与 polyfill 严格分工corejs: false不做API polyfill那是 preset-env 与 polyfill 插件的职责避免重复注入helpers仅在useBuiltIns usage时开启regenerator在useBuiltIns ! usage时开启用于转译 async/await 等 generator 语法。同时预设默认使用absoluteRuntime指向babel/runtime的绝对路径并传入version保证转译产物始终引用本预设所要求的运行时版本由于使用绝对路径会破坏“项目整体移动目录后构建哈希不变”的诉求该行为可通过显式设置absoluteRuntime: false关闭。此外 index.js 在文件末尾设置VUE_CLI_TRANSPILE_BABEL_RUNTIME环境变量配合 cli-plugin-babel/index.js 中的特殊处理使babel/runtime内未被转译的代码也能被正确编译。完整选项参考README 说明babel/preset-env的全部选项都受支持其中部分带有更智能的默认值。以下是预设自身定义与文档化的选项modules默认值webpack 构建时为falseJest 测试中为commonjs。作用显式传递给babel/preset-env控制模块语法的转换方式如amd、umd、commonjs、false等。保留 ESM 以配合 webpack 的 tree-shaking测试环境则需要 CommonJS。targets默认值读取项目的 browserslist 配置推荐写在package.json的browserslist字段Node 单元测试时为{ node: current }。作用显式传递给babel/preset-env指定目标运行环境。传入后 preset-env 将不再参考 browserslist除非同时设置ignoreBrowserslistConfig等组合。useBuiltIns默认值usage允许值usage | entry | false。作用控制 polyfill 的注入方式。usage会在转译后的代码中根据实际使用情况自动导入所需 polyfill——例如源码用到Object.assign而目标环境不支持时对应 polyfill 会被自动引入最大限度减小打包体积。注意事项usage 检测不会作用于依赖babel-loader默认排除node_modules中的文件详见下文依赖处理一节因此依赖所需的 polyfill 不会被自动检测到构建库或 Web Component 时建议设为false让使用方应用自行负责 polyfill避免把不必要的 polyfill 打进产物。官方文档 browser-compatibility.md 的 Polyfills when Building as Library or Web Components 一节也明确给出该建议。polyfills默认值[es.array.iterator, es.promise, es.object.assign, es.promise.finally]。作用在useBuiltIns: usage下需要预置包含的 core-js polyfill 列表用于覆盖那些未经 Babel 处理但又有明确 polyfill 需求的第三方依赖例如 Axios 和 Vuex 依赖 Promise。重要特性这些 polyfill 若目标环境本身已支持会被自动排除。源码中getPolyfillsindex.js通过core-js-compat的兼容数据和babel/helper-compilation-targets的isRequired逐项判断若传入的 polyfill 名在core-js-compat中不存在会抛出明确错误提示参考模块列表。默认列表的每一项都对应具体的兼容性痛点源码注释给出了依据index.jspolyfill原因es.array.iteratorPromise polyfill 单独在 IE 中无法工作必须配合该模块issue #1642es.promisewebpack 代码分割、Vuex 等场景必需es.object.assignvue-template-es2015-compiler 1.8 将模板中的对象 rest spread 编译为Object.assign()调用es.promise.finallyes.promise在 Firefox 中会替换原生 Promise 并导致finally缺失issue #2012jsx默认值true。作用设为false关闭 JSX 支持也可以传入对象来透传vue/babel-preset-jsxVue 2或vue/babel-plugin-jsxVue 3的选项例如{ injectH: false }。loose默认值false。作用设为true时生成性能更好但更不符合规范的转译代码例如类属性直接赋值而非使用Object.defineProperty同时也会传给 class-properties 插件。entryFiles默认值[]。作用多页面项目用于指定需要注入 polyfill 的入口文件列表确保所有入口都能获得 polyfill其内部实现读取环境变量VUE_CLI_ENTRY_FILES的 JSON 值作为默认值见 index.js。在 webpack 构建应用时polyfill 只会被注入到entryFiles中列出的第一个文件。其他透传/内部选项源码解构中还支持并透传给 preset-env 或相关插件的选项包括debug、bugfixes默认 true、spec、ignoreBrowserslistConfig、configPath、include、exclude、shippedProposals、forceAllTransforms、decoratorsBeforeExport、decoratorsLegacy以及上文提到的absoluteRuntime。这些选项均可按需在babel.config.js中显式传入。polyfill 注入的底层机制理解useBuiltIns: usage与polyfills选项后再看 polyfillsPlugin.js 有助于把握整体注入流程该文件实现了一个名为vue-cli-inject-polyfills的 Babel 插件在Program访问器中对entryFiles匹配的文件执行注入注入方向是逆序插入 import保证 polyfill 的执行顺序正确默认通过require.resolve解析 core-js 模块的绝对路径来导入es.array.iterator对应的路径形如core-js/modules/es.array.iterator从而规避项目中多个 core-js 版本共存造成的冲突regenerator-runtime则特殊映射到regenerator-runtime/runtimepolyfill 注入只发生在应用构建VUE_CLI_BUILD_TARGET缺省或为app且useBuiltIns usage且非 Node 测试环境时index.js其他情况如构建库、Web Component、Node 测试会跳过注入并将polyfills置空。对应的行为由测试用例 babel-preset.spec.js 完整覆盖例如polyfill detection针对ie: 9目标会注入es.promise、es.array.iterator与使用到的es.map而node: current下则全部跳过async/await验证 Promise polyfill 与regenerator-runtime/runtime的注入ES module 与 UMD 场景分别注入import/require形式的 polyfill 与 helpersexclude选项可以精确排除es.promise等 polyfill。现代模式与 Web Components 目标的特殊 targets除默认的 browserslist 目标外预设还会根据构建场景自动计算交集目标现代模式Modern Modevue-cli-service build --modern会设置VUE_CLI_MODERN_BUILD此时getModuleTargetsindex.js取“支持 ES modules 的浏览器集合”与用户 browserslist 目标的交集使现代包只保留真正必要的转译与 polyfill。测试用例modern mode always skips unnecessary polyfills验证了 Safari 12 目标下es.promise、es.map被跳过而es.promise.finally、es.global-this仍被保留的精确行为Web Components 构建VUE_CLI_BUILD_TARGET wc | wc-async时getWCTargetsindex.js以至少支持 ES2015 class 的浏览器集合Chrome 46、Firefox 45、Safari 10、Edge 13、iOS 10、Electron 0.36与用户目标取交集。两者均通过getIntersectionTargetsindex.js实现对于每个浏览器取“用户指定版本”与“约束集合最低版本”中更高的那一个确保不会为现代浏览器做多余的转译。依赖node_modules的 polyfill 处理三种方案这是 README 花费最多篇幅的实战主题。由于babel-loader默认不转译node_modules见 cli-plugin-babel/index.js 中“Dont transpile node_modules”的判断依赖中的语法与 polyfill 需求都无法被自动发现。当依赖需要 polyfill 时按依赖的代码形态选择以下方案依赖使用了目标环境不支持的 ES 语法将该依赖加入vue.config.js的transpileDependencies选项。transpileDependencies接受boolean | Arraystring | RegExp为true时转译除少数不可转译依赖core-js、webpack、css-loader 等见 cli-plugin-babel/index.js之外的全部依赖传数组时按包名或正则匹配。启用后该依赖同时获得语法转译与基于 usage 的 polyfill 检测。依赖是 ES5 代码且显式声明了所需 polyfill使用本预设的polyfills选项预置引入。推荐用这种方式而非在源码中直接import因为预设列表中的 polyfill 会在目标环境已支持时自动剔除官方文档 browser-compatibility.md 对此也有专门提示。// babel.config.js module.exports { presets: [ [vue/cli-plugin-babel/preset, { polyfills: [ es.promise, es.symbol ] }] ] }依赖是 ES5 代码却使用了未声明的 ES6 特性例如 Vuetify改用useBuiltIns: entry并在入口文件顶部添加import core-js/stable; import regenerator-runtime/runtime;或传统写法的import babel/polyfill。这会根据 browserslist 目标引入全部所需 polyfill彻底免去依赖层面的排查代价是最终包体积中会包含一些用不到的 polyfill。需要说明的是即使采用方案一babel-loader对babel/runtime的转译也受到VUE_CLI_TRANSPILE_BABEL_RUNTIME标志的约束cli-plugin-babel/index.js只有该标志开启即使用了本预设才会转译以避免无限循环。babel-loader的缓存键也纳入了vue/babel-preset-app与 browserslist 的版本信息cli-plugin-babel/index.js配置变更后缓存会自动失效。在 Vue CLI 项目中的实际配置示例综合以上内容一份覆盖常见场景的babel.config.js示例module.exports { presets: [ [vue/cli-plugin-babel/preset, { // 保持默认 usage构建库/Web Component 时建议改为 false useBuiltIns: usage, // 第三方 ES5 依赖声明的 polyfill无需时保持默认即可 polyfills: [ es.promise, es.symbol ], // 关闭 JSX默认开启 // jsx: false, // 需要更符合规范的输出则保持 false // loose: false, // 多页面项目指定注入 polyfill 的入口 // entryFiles: [src/main.js] }] ] }目标浏览器范围仍建议通过package.json的browserslist字段或独立的.browserslistrc文件声明它同时驱动 Babel 转译与 Autoprefixer 的 CSS 前缀补全具体语法与 polyfill 策略的进一步说明可参阅 browser-compatibility.md。总结vue/babel-preset-app 是 Vue CLI 浏览器兼容体系的枢纽它以babel/preset-env为核心、以 browserslist 为唯一事实来源叠加动态 import、类属性、legacy 装饰器与 JSX 支持并用transform-runtime按需抽取 helpers最后通过vue-cli-inject-polyfills插件把polyfills列表精准注入入口文件。理解它的默认值modules、useBuiltIns、targets、polyfills与三种依赖处理方案是排查“老浏览器白屏、依赖报 undefined”一类问题的关键而现代模式、Web Components 构建下的目标交集算法则体现了它在体积与兼容之间的精细平衡。【免费下载链接】vue-cli️ webpack-based tooling for Vue.js Development项目地址: https://gitcode.com/gh_mirrors/vu/vue-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考