Preset 和 Plugin 的区别
Plugin(插件)
- 粒度更细:每个插件只负责单一的转换功能
- 功能单一:例如
@babel/plugin-transform-arrow-functions只转换箭头函数 - 按需使用:可以精确控制需要哪些转换
Preset(预设)
- 插件集合:是一组插件的集合,用于简化配置
- 批量处理:一次配置,包含多个相关插件
- 常见预设:
@babel/preset-env:根据目标环境自动选择转换@babel/preset-react:React/JSX 转换@babel/preset-typescript:TypeScript 转换
配置方式
1. 使用 Plugin
javascript// babel.config.js module.exports = { plugins: [ '@babel/plugin-transform-arrow-functions', '@babel/plugin-transform-classes', // 带参数的插件 ['@babel/plugin-transform-runtime', { corejs: 3 }] ] };
2. 使用 Preset
javascript// babel.config.js module.exports = { presets: [ ['@babel/preset-env', { targets: { browsers: ['> 1%', 'last 2 versions'] }, useBuiltIns: 'usage', corejs: 3 }], '@babel/preset-react' ] };
3. Plugin 和 Preset 的执行顺序
重要规则:
- Plugin 先于 Preset 执行
- Plugin 从前往后执行
- Preset 从后往前执行
javascriptmodule.exports = { plugins: [ 'plugin-a', // 第1个执行 'plugin-b' // 第2个执行 ], presets: [ 'preset-b', // 第4个执行(preset 逆序) 'preset-a' // 第3个执行 ] };
最佳实践
1. 优先使用 @babel/preset-env
javascriptmodule.exports = { presets: [ ['@babel/preset-env', { targets: '> 0.25%, not dead' }] ] };
2. 开发自定义 Plugin
javascript// 简单的 Babel 插件示例 module.exports = function(babel) { const { types: t } = babel; return { name: 'my-custom-plugin', visitor: { Identifier(path) { // 转换逻辑 } } }; };
3. 开发自定义 Preset
javascript// 自定义 preset module.exports = function() { return { plugins: [ 'plugin-a', 'plugin-b' ] }; };
常见面试追问
-
为什么 preset 是逆序执行?
- 为了符合大多数用户的直觉,通常将更具体的 preset 放在后面
-
如何查看 Babel 实际使用了哪些插件?
- 使用
DEBUG=* babel src查看调试信息
- 使用
-
plugin 和 preset 可以混用吗?
- 可以,且非常常见,preset 处理大部分转换,plugin 处理特殊需求