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 选项:
false:不注入 polyfillentry:在入口文件全量引入usage:按代码使用情况按需引入(推荐)
转译示例
// 源代码
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 → 需要安装 polyfillBabel 配置最佳实践
// 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 11Babel、Autoprefixer、ESLint 等工具共用此配置。
现代替代方案
- esbuild:Go 编写,速度极快,但功能不如 Babel 全面
- SWC:Rust 编写,Next.js 默认使用
- Babel 仍然是生态最丰富的方案,但速度上不如 esbuild/SWC