Babel 预设 #

什么是预设? #

预设(Preset)是一组 Babel 插件的集合,用于支持特定的语法特性或场景。使用预设可以避免手动配置大量插件,简化配置过程。

text
┌─────────────────────────────────────────────────────────────┐
│                       Babel Preset                           │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │  Plugin A   │  │  Plugin B   │  │  Plugin C   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│         │                │                │                  │
│         └────────────────┼────────────────┘                  │
│                          │                                   │
│                    ┌─────▼─────┐                            │
│                    │   Preset   │                            │
│                    └───────────┘                             │
│                                                              │
└─────────────────────────────────────────────────────────────┘

官方预设列表 #

预设 说明
@babel/preset-env 智能环境预设,按需转换
@babel/preset-react React JSX 支持
@babel/preset-typescript TypeScript 支持
@babel/preset-flow Flow 类型支持
@babel/preset-modules ES 模块优化

@babel/preset-env #

@babel/preset-env 是最重要的预设,它可以根据目标环境智能地确定需要使用的插件。

安装 #

bash
npm install --save-dev @babel/preset-env

基本使用 #

javascript
// babel.config.js
module.exports = {
  presets: ['@babel/preset-env']
};

targets 配置 #

targets 用于指定目标运行环境:

javascript
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      // 字符串形式(使用 browserslist 查询语法)
      targets: '> 0.25%, not dead',

      // 对象形式(指定具体版本)
      targets: {
        chrome: '80',
        firefox: '78',
        safari: '14',
        edge: '88'
      },

      // Node.js 环境
      targets: {
        node: 'current'  // 当前 Node.js 版本
      },

      // 组合配置
      targets: {
        browsers: ['> 1%', 'last 2 versions', 'not dead'],
        node: '12'
      }
    }]
  ]
};

targets 查询语法 #

javascript
// 常用查询语法
targets: {
  // 全球使用率超过 1% 的浏览器
  browsers: ['> 1%'],

  // 最近 2 个版本
  browsers: ['last 2 versions'],

  // 排除已停止维护的浏览器
  browsers: ['not dead'],

  // 组合使用
  browsers: ['> 0.25%', 'not dead'],

  // 特定浏览器
  browsers: ['Chrome >= 80', 'Firefox >= 78', 'Safari >= 14'],

  // 排除特定浏览器
  browsers: ['not IE 11']
}

browserslist 配置 #

可以在项目根目录创建 .browserslistrc 文件或 package.json 中配置:

json
// package.json
{
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}
text
// .browserslistrc
> 1%
last 2 versions
not dead

modules 配置 #

控制模块转换方式:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      // 不转换模块(保留 ES 模块)
      modules: false,

      // 转换为 CommonJS
      modules: 'cjs',

      // 转换为 AMD
      modules: 'amd',

      // 转换为 UMD
      modules: 'umd',

      // 转换为 SystemJS
      modules: 'systemjs',

      // 自动检测(默认)
      modules: 'auto'
    }]
  ]
};

useBuiltIns 配置 #

控制 polyfill 的引入方式:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      // 不自动引入 polyfill
      useBuiltIns: false,

      // 根据使用情况按需引入(推荐)
      useBuiltIns: 'usage',

      // 根据目标环境在入口引入
      useBuiltIns: 'entry',

      // 必须指定 corejs 版本
      corejs: 3
    }]
  ]
};

useBuiltIns: ‘usage’ #

javascript
// 配置
module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'usage',
      corejs: 3
    }]
  ]
};

// 源代码
const arr = [1, 2, 3].includes(2);
const promise = Promise.resolve();

// 编译后(自动注入需要的 polyfill)
import "core-js/modules/es.array.includes.js";
import "core-js/modules/es.promise.js";
var arr = [1, 2, 3].includes(2);
var promise = Promise.resolve();

useBuiltIns: ‘entry’ #

javascript
// 配置
module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'entry',
      corejs: 3
    }]
  ]
};

// 入口文件
import 'core-js/stable';
import 'regenerator-runtime/runtime';

// Babel 会根据目标环境替换为具体的 polyfill
// 例如目标环境是 Chrome 80,则只引入 Chrome 80 不支持的 polyfill

corejs 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'usage',
      corejs: '3',           // 使用 core-js@3
      corejs: '3.21',        // 指定具体版本
      corejs: {              // 详细配置
        version: '3.21',
        proposals: true      // 启用提案阶段的 polyfill
      }
    }]
  ]
};

targets.esmodules #

针对支持 ES 模块的现代浏览器:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: {
        esmodules: true  // 支持原生 ES 模块的浏览器
      }
    }]
  ]
};

spec 配置 #

启用更符合规范的转换:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      spec: true  // 更严格但更慢的转换
    }]
  ]
};

loose 配置 #

启用更宽松的转换:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      loose: true  // 更宽松但可能不完全符合规范
    }]
  ]
};

shippedProposals 配置 #

启用已进入标准但尚未广泛支持的特性:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      shippedProposals: true
    }]
  ]
};

debug 配置 #

输出调试信息:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      debug: true  // 输出使用的插件和 polyfill 信息
    }]
  ]
};

include 和 exclude #

强制包含或排除特定插件:

javascript
module.exports = {
  presets: [
    ['@babel/preset-env', {
      include: [
        '@babel/plugin-transform-arrow-functions'
      ],
      exclude: [
        '@babel/plugin-transform-regenerator'
      ]
    }]
  ]
};

@babel/preset-react #

用于 React 项目的 JSX 转换。

安装 #

bash
npm install --save-dev @babel/preset-react

基本使用 #

javascript
// babel.config.js
module.exports = {
  presets: ['@babel/preset-react']
};

runtime 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-react', {
      // 经典转换(需要手动引入 React)
      runtime: 'classic',

      // 自动转换(自动引入 JSX 运行时)
      runtime: 'automatic'  // 推荐
    }]
  ]
};

经典转换 vs 自动转换 #

javascript
// 经典转换 (runtime: 'classic')
// 输入
const element = <div>Hello</div>;

// 输出
var element = React.createElement('div', null, 'Hello');
// 需要手动 import React from 'react';

// 自动转换 (runtime: 'automatic')
// 输入
const element = <div>Hello</div>;

// 输出
import { jsx as _jsx } from 'react/jsx-runtime';
var element = _jsx('div', { children: 'Hello' });
// 不需要手动引入 React

development 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-react', {
      development: true,  // 添加开发辅助信息
      development: process.env.NODE_ENV === 'development'
    }]
  ]
};

throwIfNamespace 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-react', {
      throwIfNamespace: true  // 抛出 XML 命名空间错误
    }]
  ]
};

其他选项 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-react', {
      runtime: 'automatic',
      development: process.env.NODE_ENV === 'development',
      useBuiltIns: true,      // 使用内置方法
      useSpread: false        // 使用 Object.assign 而不是 spread
    }]
  ]
};

@babel/preset-typescript #

用于 TypeScript 项目的类型剥离。

安装 #

bash
npm install --save-dev @babel/preset-typescript

基本使用 #

javascript
// babel.config.js
module.exports = {
  presets: ['@babel/preset-typescript']
};

isTSX 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      isTSX: true  // 允许在 .js 文件中使用 JSX
    }]
  ]
};

jsxPragma 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      jsxPragma: 'React',      // 替换默认的 React
      jsxPragmaFrag: 'React.Fragment'  // Fragment 替换
    }]
  ]
};

allowNamespaces 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      allowNamespaces: true  // 允许 JSX 命名空间
    }]
  ]
};

allowDeclareFields 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      allowDeclareFields: true  // 允许 declare 字段
    }]
  ]
};

onlyRemoveTypeImports 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      onlyRemoveTypeImports: true  // 只移除类型导入
    }]
  ]
};

optimizeConstEnums 配置 #

javascript
module.exports = {
  presets: [
    ['@babel/preset-typescript', {
      optimizeConstEnums: true  // 优化 const 枚举
    }]
  ]
};

@babel/preset-flow #

用于 Flow 类型检查项目的类型剥离。

安装 #

bash
npm install --save-dev @babel/preset-flow

基本使用 #

javascript
// babel.config.js
module.exports = {
  presets: ['@babel/preset-flow']
};

组合使用预设 #

React + TypeScript #

javascript
// babel.config.js
module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-typescript',
    ['@babel/preset-react', { runtime: 'automatic' }]
  ]
};

完整 Web 项目 #

javascript
// babel.config.js
module.exports = function(api) {
  const isProduction = api.env('production');

  return {
    presets: [
      ['@babel/preset-env', {
        targets: '> 0.25%, not dead',
        useBuiltIns: 'usage',
        corejs: 3,
        modules: false
      }],
      '@babel/preset-typescript',
      ['@babel/preset-react', { runtime: 'automatic' }]
    ],
    plugins: [
      '@babel/plugin-transform-runtime',
      isProduction && 'babel-plugin-transform-remove-console'
    ].filter(Boolean)
  };
};

Node.js 项目 #

javascript
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: { node: 'current' }
    }]
  ]
};

库开发 #

javascript
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: { node: '12' },
      modules: false  // 保留 ES 模块
    }]
  ],
  plugins: [
    ['@babel/plugin-transform-runtime', {
      useESModules: true
    }]
  ]
};

预设执行顺序 #

text
┌─────────────────────────────────────────────────────────────┐
│                     预设执行顺序                             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  配置:                                                       │
│  presets: ['a', 'b', 'c']                                   │
│                                                              │
│  执行顺序: c -> b -> a(从后往前)                            │
│                                                              │
│  ┌──────────┐                                               │
│  │ Plugin   │  先执行所有插件                                │
│  └────┬─────┘                                               │
│       │                                                      │
│       ▼                                                      │
│  ┌──────────┐                                               │
│  │ Preset c │                                               │
│  └────┬─────┘                                               │
│       │                                                      │
│       ▼                                                      │
│  ┌──────────┐                                               │
│  │ Preset b │                                               │
│  └────┬─────┘                                               │
│       │                                                      │
│       ▼                                                      │
│  ┌──────────┐                                               │
│  │ Preset a │                                               │
│  └──────────┘                                               │
│                                                              │
└─────────────────────────────────────────────────────────────┘

自定义预设 #

创建自定义预设 #

javascript
// my-preset.js
module.exports = function() {
  return {
    presets: [
      ['@babel/preset-env', {
        targets: '> 0.25%, not dead',
        useBuiltIns: 'usage',
        corejs: 3
      }]
    ],
    plugins: [
      '@babel/plugin-transform-runtime',
      '@babel/plugin-proposal-class-properties'
    ]
  };
};

使用自定义预设 #

javascript
// babel.config.js
module.exports = {
  presets: [
    './my-preset.js',
    '@babel/preset-react'
  ]
};

发布预设包 #

javascript
// @scope/babel-preset-my-preset/index.js
module.exports = function() {
  return {
    presets: [...],
    plugins: [...]
  };
};

// package.json
{
  "name": "@scope/babel-preset-my-preset",
  "main": "index.js"
}

// 使用
// babel.config.js
module.exports = {
  presets: ['@scope/babel-preset-my-preset']
};

预设最佳实践 #

1. 使用 preset-env 的智能转换 #

javascript
// 推荐:让 preset-env 智能选择插件
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.25%, not dead',
      useBuiltIns: 'usage',
      corejs: 3
    }]
  ]
};

2. 避免重复配置 #

javascript
// 不推荐:同时使用多个预设处理相同语法
module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-es2015'  // 已废弃,不要使用
  ]
};

// 推荐:只使用 preset-env
module.exports = {
  presets: ['@babel/preset-env']
};

3. 合理设置 targets #

javascript
// 不推荐:不设置 targets
module.exports = {
  presets: ['@babel/preset-env']  // 会转换所有 ES6+ 语法
};

// 推荐:设置合理的 targets
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: '> 0.25%, not dead'
    }]
  ]
};

4. 使用 browserslist 配置 #

json
// package.json
{
  "browserslist": {
    "production": [
      "> 1%",
      "last 2 versions",
      "not dead"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version"
    ]
  }
}

常见问题 #

问题一:预设顺序错误 #

javascript
// 错误:preset-react 在 preset-typescript 之前
module.exports = {
  presets: [
    '@babel/preset-react',
    '@babel/preset-typescript'  // 不会处理 TSX 文件
  ]
};

// 正确:preset-typescript 在前
module.exports = {
  presets: [
    '@babel/preset-typescript',
    '@babel/preset-react'
  ]
};

问题二:polyfill 重复 #

javascript
// 问题:多个入口重复引入 polyfill
// 解决:使用 useBuiltIns: 'usage'
module.exports = {
  presets: [
    ['@babel/preset-env', {
      useBuiltIns: 'usage',
      corejs: 3
    }]
  ]
};

问题三:模块转换问题 #

javascript
// 问题:使用 webpack 时模块被转换
// 解决:设置 modules: false
module.exports = {
  presets: [
    ['@babel/preset-env', {
      modules: false  // 保留 ES 模块,让 webpack 处理
    }]
  ]
};

下一步 #

现在你已经掌握了 Babel 预设的使用方法,接下来学习 插件系统 了解如何使用和开发插件!

最后更新:2026-03-28