Babel 是什么?
Babel 是一个 JavaScript 编译器
Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。下面列出的是 Babel 能为你做的事情:
- 语法转换
- 通过 Polyfill 方式在目标环境中添加缺失的特性(通过第三方 polyfill 模块,例如 core-js,实现)
- 源码转换 (codemods)
配置 Babel
.babelrc和babel.config.js 都是Babel的配置文件
babel 7.x 以上开始支持两种类型的配置文件, 分别是.babelrc 和 babel.config.js
babel.config.js
是在babel第7版引入的,主要是为了解决babel6中的一些问题
- .babelrc会在一些情况下,莫名地应用在node_modules中
- .babelrc的配置不能应用在使用符号链接引用进来的文件
- 在node_modules中的.babelrc会被检测到,即使它们中的插件和预设通常没有安装,也可能在Babel编译文件的版本中无效
并且支持的文件扩展名:
Babel 可以使用 Node.js 原生支持的任何文件扩展名进行配置:您可以使用.json、 .js、.cjs和.mjs, forbabel.config.json和.babelrc.jsonfiles
。
推荐使用场景:
- babel.config.json
- 你正在使用一个monorepo(可以理解为在一个项目中会有多个子工程)
- 你希望编译node_modules以及symobllinked-project中的代码
*.babelrc - 你的配置仅适用于项目的单个部分
- 需要在子目录/文件中运行一些特定的转换,比如你可能不希望一些第三方库被转码
- 综合推荐使用babel.config.json,Babel itself is using it
配置文件 .babelrc
使用 Babel 第一步就是配置此文件,放在项目根目录,此文件用于配置转码规则和插件,基本格式:
{
"presets":[],
"plugins":[]
}
预设(Presets)
Babel 的预设(preset)可以被看作是一组 Babel 插件和/或 options
配置的可共享模块。
创建预设
如需创建一个自己的预设(无论是为了本地使用还是发布到 npm),需要导出(export)一个配置对象
可以是返回一个插件数组...
module.exports = function() {
return {
plugins: ["pluginA", "pluginB", "pluginC"],
};
};
preset 可以包含其他的 preset,以及带有参数的插件。
module.exports = () => ({
presets: [require("@babel/preset-env")],
plugins: [
[require("@babel/plugin-proposal-class-properties"), { loose: true }],
require("@babel/plugin-proposal-object-rest-spread"),
],
});
预设的排列顺序
Preset 是逆序排列的(从后往前)。
{
"presets": ["a", "b", "c"]
}
将按如下顺序执行: c、b 然后是 a。
这主要是为了确保向后兼容,由于大多数用户将 "es2015" 放在 "stage-0" 之前。
预设的参数
插件和 preset 都可以接受参数,参数由插件名和参数对象组成一个数组,可以在配置文件中设置。
如果不指定参数,下面这几种形式都是一样的:
{
"presets": [
"presetA", // bare string
["presetA"], // wrapped in array
["presetA", {}] // 2nd argument is an empty options object
]
}
要指定参数,请传递一个以参数名作为键(key)的对象。
{
"presets": [
[
"@babel/preset-env",
{
"loose": true,
"modules": false
}
]
]
}
插件(plugins)
Babel 的代码转换是通过将插件(或预设)应用到您的配置文件来启用的。
使用插件
如果插件在npm 上,你可以传入插件的名称,Babel 会检查它是否安装在node_modules
. 这被添加到plugins配置选项,它采用一个数组。
{
"plugins": ["babel-plugin-myPlugin", "@babel/plugin-transform-runtime"]
}
您还可以指定插件的相对/绝对路径。
{
"plugins": ["./node_modules/asdf/plugin"]
}
插件顺序
这意味着如果两个转换插件都将处理“程序(Program)”的某个代码片段,则将根据转换插件或 预设(preset) 的排列顺序依次执行。
- 插件在 预设(preset) 前运行。
- 插件顺序从前往后排列。
{
"plugins": ["transform-decorators-legacy", "transform-class-properties"]
}
先执行 transform-decorators-legacy ,在执行 transform-class-properties
** 插件参数**
参数由插件名和参数对象组成一个数组,可以在配置文件中设置。
如果不指定参数,下面这几种形式都是一样的:
{
"plugins": ["pluginA", ["pluginA"], ["pluginA", {}]]
}
要指定参数,请传递一个以参数名作为键(key)的对象。
{
"plugins": [
[
"transform-async-to-module-method",
{
"module": "bluebird",
"method": "coroutine"
}
]
]
}
补充
1.语法转译器
@babel/preset-env
转译包
主要对 JavaScript 最新的语法糖进行编译,并不负责转译新增的 API 和全局对象。
而 Promise,Iterator,Generator,Set,Maps,Proxy,Symbol 等全局对象,以及一些定义在全局对象的方法(比如 includes/Object.assign 等)并不能被编译。
官方推荐使用,包含了所有现代js(es2015 es2016等)的所有新特性,你也可以传递一些配置给env,精准实现你想要的编译效果。
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "entry"
}
]
]
}
参数:
-
targets https://www.babeljs.cn/docs/babel-preset-env#targets
string | Array<string> | { [string]: string },targets如果在@babel/preset-env的文档中没有指定与浏览器列表相关的选项,则默认为顶级选项,否则为{}
描述您的项目支持/目标的环境。
{
"targets": "> 0.25%, not dead"
}
-
modules
"amd" | "umd" | "systemjs" | "commonjs" | "cjs" | "auto" | false,默认为"auto"。
启用 ES 模块语法到另一种模块类型的转换。请注意,这cjs
只是commonjs
.
将此设置为false
将保留 ES 模块。仅当您打算将本机 ES 模块发送到浏览器时才使用此选项。如果您在 Babel 中使用捆绑器,modules: "auto"
则始终首选默认值。
include
Array<string|RegExp>,默认为[]
始终包含的一系列插件。exclude
Array<string|RegExp>,默认为[]。
要始终排除/删除的一系列插件。useBuiltIns
"usage"| "entry"| false,默认为false。
此选项配置如何@babel/preset-env处理 polyfill。
当使用usage
或entry
选项时,@babel/preset-env
会将对core-js
模块的直接引用添加as bare imports (or requires)。这意味着core-js
将相对于文件本身进行解析并且需要可访问。
由于@babel/polyfill
已在 7.4.0 中弃用,我们建议直接core-js
通过corejs
选项添加和设置版本。
corejs
string或{ version: string, proposals: boolean },默认为"2.0"。该version字符串可以是任何受支持的core-js版本。例如,"3.8"或"2.0"。configPath
string
, 默认为process.cwd()
开始对 browserslist 进行配置搜索的起点,并上升到系统根目录直到找到。
2.API 和全局对象转译器
负责转译新增的 API 和全局对象,保证在浏览器的兼容性。比如Promise,Iterator,Generator,Set,Maps,Proxy,Symbol 等全局对象,以及一些定义在全局对象的方法(比如 includes/Object.assign 等)具体可查询https://github.com/babel/babel/blob/master/packages/babel-plugin-transform-runtime/src/definitions.js
babel polyfill
相当于一个垫片,可以转译所有 ES6 API 和全局对象。
缺点:增加包体,比如仅是使用到一种 ES6 新增 API,他也会增加所有的转移语法。
3.jsx,flow,TypeScript 等插件转译器
@babel/preset-react
当你使用 react 项目时,需要使用此包配合转译
安装:npm install --save-dev @babel/preset-react
引用:在 .babelrc 中添加配置
"presets": ["@babel/preset-react"]
@babel/preset-typescript
当你项目是用 TypeScript 编写时,需要使用此包配合转译
安装:npm install --save-dev @babel/preset-typescript
引用:在 .babelrc 中添加配置
"presets": ["@babel/preset-typescript"]
参考:
https://www.babeljs.cn/docs/configuration
https://blog.csdn.net/weixin_45151873/article/details/118572216
https://zhuanlan.zhihu.com/p/84083454