• babel只进行JS语法的语法转换,对于JS新的API是无法进行转换的,比如Map, Set, Promise等全局对象
  • 在全局对象的上方法,比如ES6 新增的 Array.find方法,babel就无法转换

1. targets

  • 配置参数targets表示我们要支持那些平台和那些版本
  • 也可以配置浏览器的版本号,浏览器的版本号越低,引入的polyfill越多,版本号越高,引入的越少
    1. {
    2. test: /\.js$/,
    3. use: {
    4. loader: "babel-loader",
    5. options: {
    6. targets: {
    7. "browsers": ["last 2 versions"] // ["IE 6", "chrome 90"]
    8. }
    9. }
    10. }
    11. }

2. babel-polyfill

babel-polyfill是通过向全局对象或者内置对象上的prototyoe上添加方法来实现的,缺点是会造成全局空间污染

3. useBuiltIns

@babel/preset-env是转换语法的插件预设,默认是只转换语法,不转换API的,如果要转换API,需要开启useBuiltIns配置才能转换API和实例方法

useBuiltIns有三个选项

  • false: 默认是false,表示不对polyfill做处理,如果引入@bebel/polyfill,则无视配置浏览器的兼容,引入所有的polyfill
  • “entry”, 入口文件引入@bebel/polyfill
  • “useage”,自动判断代码中用到了什么API来按需加载

3.1 useBuiltIns: false

  1. {
  2. test: /\.js$/,
  3. use: {
  4. loader: "babel-loader",
  5. options: {
  6. presets: [
  7. ["@babel/preset-env", {
  8. useBuiltIns: false
  9. }]
  10. ]
  11. }
  12. }
  13. }

3.2 useBuiltIns: “entry”

  • 在项目入口文件引入一次(多次会报错)
  • 需要在项目入口文件引入 import “@babel/polyfill
  • 会根据配置的浏览器的兼容性来引入浏览器不兼容的polyfill
  • 需要指定core-js的版本,默认是2,需要在入口文件配置 import “@babel/polyfill
  • 如果core-js指定的版本是3,则需要在入口文件把import “@babel/polyfill” 改成 import “core-js/stable”; import “regenerator-runtime/runtime”
  • core-js就是polyfill方法的实现
  • 缺点是只会根据浏览器的版本来引入,如果代码中没有使用新的API也会引入当前浏览器不兼容的polyfill


npm install —save core-js@2 npm install —save core-js@3

/src/index.js

  1. // core-js: 2
  2. import "@babel/polyfill";
  3. // core-js: 3
  4. import 'core-js/stable';
  5. import 'regenerator-runtime/runtime';
  6. let sum = (a, b) => a + b;
  7. let promise = Promise.resolve();
  8. console.log([1, 2, 3].find(item => item === 2));
  1. {
  2. test: /\.js$/,
  3. use: {
  4. loader: "babel-loader",
  5. options: {
  6. presets: [
  7. ["@babel/preset-env", {
  8. useBuiltIns: "entry",
  9. corejs: 3 // corejs: { version: 3 }
  10. }]
  11. ]
  12. }
  13. }
  14. }


3.3 useBuiltIns: “usage”

  • 如果配置成usage之后,usage会根据浏览器兼容的配置和你代码中用到的API来按需加载
  • 当设置成usage之后,不需要在引入@babel/polyfill
  1. {
  2. test: /\.js$/,
  3. use: {
  4. loader: "babel-loader",
  5. options: {
  6. presets: [
  7. ["@babel/preset-env", {
  8. useBuiltIns: "usage",
  9. corejs: 3 // corejs: { version: 3 }
  10. }]
  11. ]
  12. }
  13. }
  14. }

4. babel-runtime

  • babel-runtime为了解决全局空间污染的问题单独提供的的包,用于解决编译模块的工具函数
  • 它更像是一种按需加载,需要用到什么模块就引入什么模块
  • 缺点就是用什么都需要手动引入,非常麻烦且繁琐

npm i babel-runtime —save-dev

  1. import Promise from '@babel-runtime/core-js/promise';
  2. let promise = Promise.resolve();


5. babel-plugin-transform-runtime

  • 是为了解决多个文件引用了相同的 helper(帮助函数) 提取到运行时
  • 新的API全局方法变成局部引用,会生成多个方法的文件导出来使用

npm i @babel/plugin-transform-runtime @babel/runtime-corejs3 —save-dev

  1. {
  2. test: /\.js$/,
  3. use: {
  4. loader: "babel-loader",
  5. options: {
  6. presets: [
  7. ["@babel/preset-env", {
  8. useBuiltIns: "usage",
  9. corejs: 3 // corejs: { version: 3 }
  10. }]
  11. ]
  12. },
  13. plugins: [
  14. ["@babel/plugin-transform-runtime", {
  15. corejs: 3,
  16. helpers: true
  17. }]
  18. ]
  19. }
  20. }

5.1 corejs: 3

  • 当我们使用ES6的静态事件 或者 内置对象的方法时,会自动引用babel-runtime/core-js

5.2 helpers: true

  • 移除内联的babel helpers并替换使用babel-runtime/helpers
  • 避免内联的helper在多个文件中重复出现

6. 总结

平时项目开发

  • 对于平时项目开发的时候,采用@babel/preset-env来处理兼容问题,缺点是污染全局变量
  • useBuiltIns: “usage”,来判断浏览器的版本和自动按需引入
  • 通过配置@babel-plugin-transform-runtime的helpers: true来减少公共文件的重复生成,提取成公共文件

对于包和库开发的时候

  • 尽量减少全局空间的污染
  • 可以采用@babel-plugin-transform-runtime的corejs:3 来做polyfill的兼容处理