刚开始使用babel的时候,很多童鞋只是单纯跟着官网或则其他人的代码去安装一大堆bbabel相关的npm包,但是并不知道具体每个包都是什么样的作用,本文就是来阐述日常开发时用到的babel全家桶分别的作用、使用场景以及其原理。
什么是babel
首先来看一下babel是什么?
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
上面是官方文档的描述,翻译过来就是“babel是一个工具链,用来将es2015+的代码转化成在现有的或则更早的浏览器环境可以运行的向后兼容的JS语法”
// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
如何使用
babel的使用有很多种方式,本文主要来描述下日常开发经常使用到的两种方式:命令行方式使用以及结合webpack来使用:
命令行方式使用
1. 安装babel
```
npm i @babel/core @babel/cli -D
```
2. 在package.json中配置起使用方式
```
"scripts": {
"build": "babel src --out-dir ./",
},
```
这样就可以将/src下的js文件编译之后输出到根目录下了
webpack使用
结合webpack使用的时候就需要babel对应的loader,之后再webpack的配置文件下配置完成就可以
注: @babel/core是babel7版本的基础包,是必须引入的。
```
npm i @babel/core babel-loader -D
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'bin')
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
exclude: /node_modules/,
}
]
}
};
```
配置
通过上述方式使用之后,就可以使用babel了,但是此时会发现编译之后并没有什么变化,这是因为我们需要增加配置信息来告诉babel要把代码编译成符合什么标准的以及某些编译还需要增加插件的应用,于是要解决以上两个问题,我们就需要引入presets和plugins。
配置文件
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
}
}]
],
"plugins": ["@babel/transform-runtime"]
}
babel编译过程中会读取相应的配置文件来编译源代码
presets
预设其实就是一个预先设定的插件列表,使用一个预设就是将这个预设规定的全部插件安装并使用,但是随着插件的不断增多,我们不可能会去记忆所有的语法功能对应的版本,于是出现了preset-env。
preset-env其实相当于是一个智能预设,会根据在配置文件中设置的目标浏览器来转化成兼容的代码。
```
npm i @babel/preset-env -D
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
}
}]
],
}
```
plugins
上述步骤之后基本上可以使用ES 2015+的一些特性了,但是会有一些如新的内置函数(Promise,Set,Map),静态方法(Array.from,Object.assign),实例方法(Array.prototype.includes)等需要一些工具函数的处理,这时就需要用到plugins了,而babel的plugins分别有两种:plugin-transform-runtime和babel-polyfill。
- plugin-transform-runtime
根据官方文档的描述,babel在用工具函数来转化语法的时候会产生很多的冗余代码,导致程序代码冗余,此时推出了plugin-transform-runtime,该插件的作用有两个:
1. 将编译时生成的工具函数映射到runtime上去,这样可以避免工具函数的冗余,因此@babel/runtime是一个运行时需要的插件;
2. 建立了一个沙盒环境,不会去污染全局变量,因此比较适合写一些公用库或则组件
```
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
```
编译后如下:
```
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
```
可以看到直接引用的是runtime下的模块,这样的话就不会出现重复模块了
- babel-polyfill
babel-polyfill一般用在命令行工具或则是开发app的时候,在入口处调用,之后会被放置到全局空间,根据目标浏览器去模拟一些工具函数的行为。
```
npm install --save @babel/polyfill
import "@babel/polyfill";
```
但是由于babel-polyfill是模拟了整个ES 2015+的环境,因此并不被建议全部直接导入,而是配合presets下的useBuiltIns属性一起来使用或则手动去导入需要的所有模块。
```
.babelrc
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": ["> 0.25%", "not dead"]
},
"useBuiltIns": "usage"
}]
],
}
```
编译之后的结果为:
```
require("core-js/modules/es6.array.from");
require("core-js/modules/web.dom.iterable");
require("core-js/modules/es6.array.iterator");
require("core-js/modules/es6.object.to-string");
require("core-js/modules/es6.string.iterator");
require("core-js/modules/es6.map");
```
根据名字可以看出来是将用到的模块都单个引入,减小了包体积
注:本项目采用babel 7,webpack 4