Babel是将ES6以及以上版本的代码转换为ES5代码的工具,用于适应低版本浏览器。简单来说,功能有以下三个:
npm install --save-dev @babel/core @babel/cli
包含了babel的核心功能。
帮助我们在终端使用babel命令的工具。
一般使用babel.config.js
或者.babelrc
文件作为配置文件。
其中,主要的两个属性有:
以.babelrc
为例:
{
"plugins":["transform-decorators-legacy", "transform-class-properties"],
"presets":[]
}
可以直接在数组中加入插件的名称,babel会检查他是否被安装到node_module目录下。
也可以指定插件的相对或绝对路径。
如果插件前缀为babel-plugin-
,可以使用简称:
{
// 实际上是同一个插件
"plugins": ["myPlugin","babel-plugin-myPlugin"]
}
{
// 冠名插件也同样适用
"plugins": ["@org/babel-plugin-name","@org/name"]
}
插件的执行顺序有两点:
{
"plugins":["transform-decorators-legacy", "transform-class-properties"],
}
先执行transform-decorators-legacy
,后执行transform-class-properties
。
插件可以进行传参,参数对象与插件名字共同组成一个数组。
{
"plugins": [
[
"transform-async-to-module-method",
{
"module": "bluebird",
"method": "coroutine"
}
]
]
}
presets就是一堆插件的组合,方便我们在编译的时候直接使用。
{
"presets": ["babel-preset-myPreset"]
}
类似于plugins,直接在presets参数中设置就可以,babel会自动检查该预设是否已经安装到node_module下。
如果preset名称前缀为babel-preset-,可以使用简称:
{
// 这两个是一样的
"presets": ["myPreset","babel-preset-myPreset"]
}
与plugins不同,presets的执行顺序是从后往前的。
{
"presets": [
"a",
"b",
"c"
]
}
会按c→b→a的顺序来执行。这是为了确保向后兼容。
与plugins一样,presets也可以传递参数,参数对象和预设名共同组成一个数组:
{
"presets": [
["@babel/preset-env", {
"loose": true,
"modules": false
}]
]
}
这其实不算一个插件或者预设,但是在项目中经常会使用到,于是把它添加到这里一并写。
在Webpack中使用的loader配置,可以在options参数中配置plugins和presets。
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
babel的一个预设包,可以根据配置的目标浏览器或运行环境来按需自动将ES6+的代码转换为ES5。
{
"presets": [
[
"env",
// 以下为参数配置
{
// 将ES6 module转换为其他规范
"modules": false,
// 为polyfills 应用 @babel/preset-env
"useBuiltIns": true,
// 目标环境配置
"targets": {"browsers": ["last 2 versions", "safari >= 7", "ie>=9"]}
}
],
...
}
可参考:https://cloud.tencent.com/developer/article/1470739
是关于babel在不同阶段ES2015+语法提案支持的转码规则模块。
提案一般分为以下阶段:
在Babel7.0之后这个预设似乎已经不被再支持。
Babel默认只转换新的JavaScript语法,而不转换新的API(如Iterator、Generator、Set、Map等),以及一些定义在全局对象上的方法都不会转码。如果想要使用这些新的方法和对象,就需要使用babel-polyfill为当前环境提供一个垫片。它可以帮助模拟一整个ES2015+的运行环境。
需要注意的是,它是通过向全局对象和内置对象的prototype上添加方法来实现的,所以会造成全局变量空间污染。
// 在js文件中
import 'babel-polyfill'
// 在webpack.config.js中
entry: {
main: ['@babel/polyfill', './main.js']
},
// 在.babelrc中通过@babel/preset-env进行设置,这样可以不用引用@babel/polyfill
{
"presets": [["@babel/preset-env", {"useBuiltIns": "usage", "corejs": 2}]],
}
除了@babel/polyfill
以外,提供垫片的方式还有使用babel-runtime
和babel-plugin-transform-runtime
插件。
@babel/polyfill
虽然方便解决了新语法中API不转换的问题,但是它污染了全局环境,并且在每一个打包出来的文件中添加重复的辅助代码,这样就会导致编译后项目代码的体积很大。@babel/polyfill
便于我们开发第三方应用,但如果我们需要发布代码或者库的话,就会导致问题。
babel-runtime
是单独的用于代码编译的辅助函数包,由于没有额外加工,所以使用的时候需要自己在每一个文件中require
引入。但如果许多文件中都要使用同一个模块,这种方式就显得很繁琐。
babel-plugin-transform-runtime
就是为了解决上面的问题而产生的,它会帮助我们自动并且按需引入babel-runtime
中的工具函数。这样可以减小项目体积。
babel-runtime
和babel-plugin-transform-runtime
一般会同时安装,同时使用。
// 无参数
{
"plugins": ["@babel/plugin-transform-runtime"]
}
// 有参数
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false,
"version": "7.0.0-beta.0"
}
]
]
}
下面是一个典型的.babelrc配置文件(vue-cli中的):
{
// presets预设配置
"presets": [
// 使用babel-presets-env
["env", {
// 是否将ES6 module转换为其他规范
"modules": false,
// 目标环境
"targets": {
// 支持的浏览器版本设置,具体可以参看Browserslist
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
// 使用babel-presets-stage-2
"stage-2"
],
// plugins插件设置
"plugins": ["transform-vue-jsx", "transform-runtime"],
// 编译过程中是否产生注释
"comments": false,
// 在特定环境中设置的特定配置,会覆盖上面的配置
// env的值将会从process.env.BABEL_ENV中获取,没有的话查找process.env.NODE_ENV,都没有的话设置为development
"env": {
"test": {
// 特定环境下使用的预设
"presets": ["env", "stage-2"],
// 特定环境下使用的插件
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
}
}
}
此博客作为学习过程中笔记,知识浅薄,如有错漏,请指出(鞠躬)。