Babel 的作用是什么?preset 和 plugin 的关系?

Babel 是什么

Babel 是 JavaScript 编译器,将 ES6+ 代码转译为兼容旧浏览器的 ES5 代码。

工作流程

源代码 → Parse(解析AST) → Transform(转换AST) → Generate(生成代码)

preset 和 plugin

plugin:单个转换功能
preset:一组 plugin 的集合

// .babelrc / babel.config.json
{
  "presets": [
    "@babel/preset-env",      // 根据 browserslist 自动选择 plugin
    "@babel/preset-react",     // JSX → JS
    "@babel/preset-typescript" // TS → JS
  ],
  "plugins": [
    "@babel/plugin-proposal-optional-chaining", // ?.
    ["@babel/plugin-proposal-decorators", { "legacy": true }]
  ]
}

@babel/preset-env

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "chrome": "60",
          "firefox": "60",
          "safari": "11"
        },
        "useBuiltIns": "usage",  // 按需 polyfill
        "corejs": 3
      }
    ]
  ]
}

useBuiltIns 选项:

转译示例

// 源代码
const fn = (a = 1, ...rest) => ({ a, ...rest })
class Person { #name = 'Tom' }

// 转译后(简化)
var fn = function fn() {
  var a = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1
  // ...
}
function _defineProperties(target, props) { /*...*/ }
var Person = function Person() {
  Object.defineProperty(this, '_name', { value: 'Tom', writable: true })
}

polyfill vs transform

方式 作用 示例
transform 语法转译 箭头函数 → function
polyfill API 补丁 Promise、Array.includes
// transform:语法转译
const fn = () => {}  →  var fn = function() {}

// polyfill:API 补丁(需要额外引入 core-js)
Array.prototype.includes  →  需要安装 polyfill
Promise                   →  需要安装 polyfill

Babel 配置最佳实践

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.25%, not dead',
      useBuiltIns: 'usage',
      corejs: 3
    }],
    '@babel/preset-react',
    '@babel/preset-typescript'
  ],
  plugins: [
    // Stage 3+ 提案
    ['@babel/plugin-proposal-decorators', { legacy: true }],
    '@babel/plugin-proposal-class-properties'
  ]
}

browserslist

# .browserslistrc
> 0.5%
last 2 versions
not dead
not ie 11

Babel、Autoprefixer、ESLint 等工具共用此配置。

现代替代方案

同分类其他题目