Skip to content

该如何配置 babel

配置方式一 entry

1、这种方式将 polyfill API 挂载到 window 上,或者挂载到原型上。

2、提供所有 targets 不支持的 api。体积可能稍微有点大。(不过不用那么在意)

3、不用担心目标环境不识别第三方库的代码里用到新语法。

在入口文件中导入 core-js

js
// main.js
import "core-js/stable";

babel.config.js

js
module.exports = {
  presets: [
    [
    // 需要下载依赖 @babel/preset-env
    '@babel/preset-env', 
      {
        // modules 设置为 false 后,编译产生的辅助函数会以 esm 方式导入
        // 这样有利于打包工具比如 webpack 静态分析,进行 treeshaking 减少代码体积。
        modules: false,
        // 设置代码需要兼容目标环境
        // 如果为空对对象,则代表兼容最古老的浏览器
        // 查找 targets 配置的顺序为 
        // 1、preset-env 下的 targets
        // 2、babel 配置文件的 targets
        // 3、package.json 中的 browserslist
        // 4、项目根目录下的 browserslist
        targets: {},
        // useBuiltIns 为 usage 时,corejs 才能设置为对象形式
        corejs: '3.27.2',
        useBuiltIns: "entry",
      }
    ]
  ],
  plugins: [
    // 需要下载依赖 @babel/plugin-transform-runtime 和 @babel/runtime
    '@babel/plugin-transform-runtime' 
  ]
};

core-js

core-js 包里含有以下模块:

参考每个文件夹的作用:https://github.com/zloirock/core-js#commonjs-api

js
// polyfill all `core-js` features, including early-stage proposals:
import "core-js";
// or:
import "core-js/full";
// polyfill all actual features - stable ES, web standards and stage 3 ES proposals:
import "core-js/actual";
// polyfill only stable features - ES and web standards:
import "core-js/stable";
// polyfill only stable ES features:
import "core-js/es";

// if you want to polyfill `Set`:
// all `Set`-related features, with early-stage ES proposals:
import "core-js/full/set";
// stable required for `Set` ES features, features from web standards and stage 3 ES proposals:
import "core-js/actual/set";
// stable required for `Set` ES features and features from web standards
// (DOM collections iterator in this case):
import "core-js/stable/set";
// only stable ES features required for `Set`:
import "core-js/es/set";
// the same without global namespace pollution:
import Set from "core-js-pure/full/set";
import Set from "core-js-pure/actual/set";
import Set from "core-js-pure/stable/set";
import Set from "core-js-pure/es/set";

// if you want to polyfill just required methods:
import "core-js/full/set/intersection";
import "core-js/actual/array/find-last";
import "core-js/stable/queue-microtask";
import "core-js/es/array/from";

// polyfill iterator helpers proposal:
import "core-js/proposals/iterator-helpers";
// polyfill all stage 2+ proposals:
import "core-js/stage/2";

配置方式二 usage

1、这种方式和 entry 一样,也会将 polyfill 注入到全局。

2、它会根据目标环境,只把代码里用到的并且在目标浏览器里不支持的 api 进行垫片处理。

3、但是第三方依赖使用了不兼容 api,是不会垫片的。也就可能会报错。

所以使用这种方式,需要手动引入一些第三方依赖使用到的 polyfill。

babel.config.js

js
module.exports = {
  presets: [
    [
    // 需要下载依赖 @babel/preset-env
    '@babel/preset-env', 
      {
        // modules 设置为 false 后,编译产生的辅助函数会以 esm 方式导入
        // 这样有利于打包工具比如 webpack 静态分析,进行 treeshaking 减少代码体积。
        modules: false,
        // 设置代码需要兼容目标环境
        // 如果为空对对象,则代表兼容最古老的浏览器
        // 查找 targets 配置的顺序为 
        // 1、preset-env 下的 targets
        // 2、babel 配置文件的 targets
        // 3、package.json 中的 browserslist
        // 4、项目根目录下的 browserslist
        targets: {},
        // useBuiltIns 为 usage 时,corejs 才能设置为对象形式
        // 设置 proposals 的值
        corejs: {
          version: '3.27.2',
          // 是否编译提案阶段 ES6+ API
          proposals: false
        },
        useBuiltIns: "usage",
      }
    ]
  ],
  plugins: [
    // 需要下载依赖 @babel/plugin-transform-runtime 和 @babel/runtime
    '@babel/plugin-transform-runtime' 
  ]
};

配置方式三 false

不会在编译后的代码中添加 polyfill。

babel.config.js

js
module.exports = {
  presets: [
    [
    // 需要下载依赖 @babel/preset-env
    '@babel/preset-env', 
      {
        // modules 设置为 false 后,编译产生的辅助函数会以 esm 方式导入
        // 这样有利于打包工具比如 webpack 静态分析,进行 treeshaking 减少代码体积。
        modules: false,
        // 设置代码需要兼容目标环境,会向上寻找配置文件
        targets: {},
        // useBuiltIns 不为 false,这个选项才有用
        corejs: '3.27.2',
        useBuiltIns: false,
      }
    ]
  ],
  plugins: [
    '@babel/plugin-transform-runtime' 
  ]
};

非全局注入方式

上面一、二两种方式是会把 polyfill api 注册到全局的。

@babel/plugin-transform-runtime

如果我们不想以全局的方式污染的方式垫平我们的 ES6+ API,我们 corejs 就不能为 false,并且优先使用 @babel/runtime-corejs3 这个包来垫平(设置为 3)

js
// package.json
"browserslist": [
    "chrome 80"
]

module.exports = {
    targets: {chrome: 80}, // 在这里添加
    // 用于转换语法
    presets: ['@babel/preset-env'],
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
              // 默认为 true,开启从 @babel/runtime 里引入辅助函数
              // 设置为 fale 会变为内联方式
              helpers: true,
              // 默认为 true
              // 我们的源码里面使用了 async function() {}等异步函数,
              // 或者 fuction* myGenerator() {}这种 Generator 函数的话,
              // 就会需要用到 regenerator-runtime 这个包来编译。
              // Babel >= 7.18.0,regenerator-runtime 包里的内容,
              // 会以局部变量的方式内联注入到我们的代码中,
              // 这样我们就不需要全局提供一个 regeneratorRuntime 对象。
              // 设置为 true 将 regeneratorRuntime 对象从 @babel/runtime 引入
              // 设置为 false 会变为内联方式
              regenerator: true,
              // 这个配置项一旦不为 false,就代表会使用 polyfill。
              // 就是用来设置我们的要垫平的 ES6+ API,以不污染全局局部变量方式垫平。
              // 最好使用 core-js 3
              corejs: "3"
            }
        ]
    ]
}

TIP

corejs 的三个值:

对应依赖补充
false(默认值)@babel/runtime
2@babel/runtime-corejs21. 只能编译支持全局变量(如 Promise)和静态属性(如 Array.from);2. 不能编译实例相关方法([].includes)
3@babel/runtime-corejs31. 既能编译能编译支持全局变量和静态属性,又能编译实例方法;2. 开启 proposals: true,还可以编译提案阶段的 API

优化,设置 targets

js
// package.json
"browserslist": [
    "chrome 80"
]

// 或者在顶层添加
module.exports = {
    targets: {chrome: 80}, // 在这里添加
    presets: ['@babel/preset-env'],
    plugins: [
        [
            "@babel/plugin-transform-runtime",
            {
                ...
            }
        ]
    ]
}

Released under the MIT License.