babel(巴别塔),圣经里面上帝为了阻止人们建造巴别塔(通天之塔),上帝让人类说不同的语言,使人类相互之间不能沟通,计划因此失败,人类自此各散东西。
JavaScript 的 babel 则是为了把各个版本的 JavaScript 翻译成同一种版本或者为它们提供统一的运行环境。
7.0 之前版本和之后的版本变化较大,很多包的名字做了修改,为了统一名称,统一修改为@babel 开头,例如 babel-core 修改为@babel/core。
对照表
7.0 之前 | 7.0 之后 | 备注 |
---|---|---|
babel-core | @babel/core | |
babel-polyfill | @babel/polyfill | 7.4 之后弃用,使用其它的代替 |
babel-runtime | @babel/runtime |
包 | 简介 | 备注 |
---|---|---|
babel-loader | webpack 的插件加载代码用。 | webpack 使用 |
@babel/core | babel 的核心,编译器,提供转换的 API。 | 转换语法 如 箭头函数,class语法 |
core-js | 给低版本浏览器提供接口的库。分为 core-js@2 和@core-js@3 | 提供如:Promise 全局变量 实例方法 Array.fill等等 |
regenerator-runtime | 提供独立的函数的运行时,es5环境下的es6的generator实现 | 包含regenerator模块。 生成器函数(function*(),yeil)、async、await函数. |
@babel/polyfill | 给低版本的浏览器提供接口库 ,本质是由 core-js 和 regenerator-runtime 组成的。 | 7.4 弃用 |
@babel/helpers | 定义了一些处理新的语法关键字的辅助函数,把需要的辅助函数当做一个模块引入代码 | @babel/core 在处理的时候也会向代码中插入帮助函数,它的处理方法是在每个文件中都插入相应的帮助函数, @babel/helpers 则是把帮助函数当做模块引入,每个文件只需要调用这个模块就可以了。 这个包基本可以视为供babel自己用的,我们自己也用不着它,好像也不让我们使用 |
@babel/plugin-transform-runtime | 引入垫片的时候借助的插件 | 移除@babel/core 在转换过程中插入的函数,替换为引用@babel/helpers 中的函数, |
@babel/runtime | 包含@babel/helpers 和 regenerator-runtime | 功能就是这两个包的组合 |
@babel/runtime-corejs2 | 由 core-js@2、@babel/helpers 和 regenerator-runtime 组成 | 功能这三个包的组合 |
@babel/runtime-corejs3 | 由 core-js@3、@babel/helpers 和 regenerator-runtime 组成 | 功能这三个包的组合 |
@babel/preset-env | 插件集预设配置, | 这个预设包含所有转换ECMA标准语法的插件,但是不包含处于各个stage阶段的提案。 |
@babel/preset-stage-X | 插件集,包含 stage-0,1,2,3 | V7.0 后 弃用,这些插件集中语法特性的并不一定能够确定进入最终的标准,因为有人可能会无限制的在生产环境中使用它们导致一些问题,所以 babel 官方弃用了它们。 |
查看各个提案处于哪个阶段
关于插件集@babel/preset-env:我们在进行语言转换给浏览器提供垫片(polyfill)的时候,有几种选择,
- 全部引入,即把所有的垫片全部引入,这样有些功能我们可能就没有使用,而引入它们的垫片白白增加了大量的无效代码。
- 手动按需引用,比如当前文件用到了什么,就在文件中引入什么。例如我们文件中使用了 Promise,就在文件中引入,
import '@babel/runtime-corejs3/core-js/promise'
,这样带来的问题是,如果多个文件使用了它,每个文件都要引入。- 使用 webpack 打包,我们可以把所有需要的垫片收集起来,统一在入口文件中引入,这样就只需要引入一次即可。但是如果垫片很多的话,在入口文件里面就会出现一排排的,重复相似代码
import "@babel/runtime-corejs3/core-js/promise"; import "@babel/runtime-corejs3/core-js/xxx"; import "@babel/runtime-corejs3/core-js/xxx"; import "@babel/runtime-corejs3/core-js/xxx";
为了处理这样的代码,所以引入了插件集。插件集会根据配置自动转换语法、引入的垫片,就不需要在入口处放置一大堆声明了。
安装相关的包
npm i @babel/core @babel/preset-env babel-loader -D
配置 webpack
// webpack.config.js
module: {
rules: [
...
{
test: /\.js$/,
exclude: /node_moduels/,
use: {
loader: "babel-loader"
}
}
],
}
....
配置 babel
// babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = [ ... ];
const plugins = [ ... ];
return {
presets,
plugins
};
}
babel.config.json、.babelrc、.babelrc.json 其实都是一个JSON文件而已,内容都是一样的。以及在package.json还有loader中配置babel内容没有多大差别。
官方相关配置文档
根据自己的需要选择配置文件类型。。。。。
就当前情况暂时先选择,.babelrc 来配置。
{
"presets": [
[
"@babel/preset-env", // 也可以简写为 “@babel/env”
{
"targets": {
"chrome": "68",
"ie": "11"
}
}
]
]
}
可以通过 .browserslistrc(推荐)指定目标环境,很多项目都是通过这个来确定目标环境的。
如果提供了.browserslistrc
,就不能再指定target了,因为target会覆盖.browserslistrc
的配置,如果指定了target又想使用.browserslistrc
需要指定ignoreBrowserslistConfig
属性。
babel-polyfill 已经被废弃,但是 core-js 和它的作用类似。
全部引入import "core-js";
,也可以按照需要使用什么引入什么。
安装 babel 相关的包
npm i @babel/core @babel/preset-env babel-loader -D
配置文件
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": "68",
"ie": 10
},
"useBuiltIns": "entry",
"corejs": 2
}
]
]
}
参数介绍,
target: 转换结果的目标,代码最终的执行环境,根据目标环境判断是否需要对语法进行转换,对那些语法进行转换例如箭头函数、class 语法等等。
useBuiltIns: false | “entry” | “usage”
选项 | 描述 |
---|---|
false (默认值) | 此时 corejs 属性无效,不引入垫片,仅仅根据 target 属性判断后转换相应的语法, |
“entry” | 在入口处手动引入垫片,根据目标环境自动补全缺失的全部功能,无论我们的代码是否使用了对应的功能。 |
“usage” | 自动检测目标环境的同时检测文件中使用的需要引入的垫片并自动引入对应的垫片。(官方推荐),目标环境不支持但是我们的代码也没有使用的不会补全。 |
corejs: 2| 3
corejs 属性仅仅在 useBuiltIns 设置为 非 false 的时候有效。
corejs 设置不同参数的时候注意安装对应的包。如果 useBuiltIns 为 “entry” 的时候还需要手动在入口引入。
corejs 选项 | 需要额外安装的包 | 备注 |
---|---|---|
2(默认值) | npm i core-js@2 -S | 已停止新增功能 |
3 | npm i core-js@3 -S | |
现在通过 npm i core-js -S安装的时候如果不指定版本,已经默认会安装3了。 |
runtime-transform 和 core-js 类似,但是 transform-runtime 提供的沙箱式的垫片单独生成了一个运行沙箱,不会污染全局变量。一般用在当代码运行在我们不可控的环境中的时候,例如;发布的 npm 包
安装相关包
npm i @babel/core @babel/preset-env @babel/plugin-transform-runtime babel-loader -D
配置文件
// .babelrc
{
"presets": [["@babel/preset-env"]],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
}
corejs 设置不同参数的时候需要安装对应的包。
corejs 选项 | 描述 | 需要额外安装的包 |
---|---|---|
false(默认值) | 只辅助转换语法,如:箭头函数 、class 语法 | npm i @babel/runtime -S |
2 | 在 false 的基础上增加支持全局变量和静态方法,例如 Promise,Array.from | npm i @babel/runtime-corejs2 -S |
3 | 在 2 的基础上增加支持实例方法 如 [].includes() | npm i @babel/runtime-corejs3 -S |
两种使用方式的区别在于是否污染全局环境。不能同时使用。
在 VUE 中推荐使用 polyfill 的方式。因为以 transform-runtime 方式使用的时候,默认情况下只会转换我们的代码,不会给 node_module 中的库添加垫片什么的,如果想让它转换 mode_module 中的代码还需要使用 babel.config.js 来特殊配置,而且转换的结果还不一定能够使用。node_module 中的库可能会自带垫片,但是如果你想使用功能 vuex, 浏览器控制台就会报错,提示需要我们提供全局的垫片,因为 vuex 没有自带垫片。
我们自己开发 web 程序,目前最省事就是进行如下配置,把所有的 polyfill 引入这样也就不用担心缺少什么东西了。到了后面有时间如果想优化打包,比如减少打包结果的体积什么的,可以再进行优化。前期开发直接全部引入,不要用什么再引入什么不然来回修改显得有点麻烦。
要安装的包npm i @babel/core @babel/preset-env babel-loader -D
和npm i core-js@3 -S
;
在文件入口 index.js 开头引入 core-js
// index.js
import 'core-js/stable`
或者也可以在 webpack 打包配置中增加 core-js;
// webpack.config.js
...
module.exports = {
...
entry: {
main: ["core-js/stable", "./src/index.js"]
},
...
}
babel 的配置文件
// .babelrc
{
"presets": [
[
"@babel/preset-env",
{
// target 要根据自己的情况进行配置
"targets": {
"chrome": "68",
"ie": 10
},
"useBuiltIns": "entry",
"corejs": 3
}
]
]
}