一、和Babel相关的几个包

1、Babel

1.1 Babel是一个工具链,主要用于将采用ECMAScript 2015+语法编写的代码转换为向后兼容的 JavaScript语法,以便能够运行在当前和旧版本的浏览器或其他环境中。

1.2 Babel提供以下两个功能组成:

  • 编译ES6+最新语法(let、class、() => {}等)
  • 实现旧版本浏览器不支持的ES6+的API(Promise、Symbol、Array.prototype.includes等)

2、Babel配置文件大致结构

1
2
3
4
5
6
7
8
9
10
11
12
13
// babel.config.js
module.exports = {
...,
envName: "development",
plugins: [],
presets: [],
passPerPreset: false,
targets: {},
browserslistConfigFile: true,
browserslistEnv: undefined,
inputSourceMap: true
...
}

我们一般主要用到的就是plugins、presets这两个

3、和Babel相关的几个主要的包

3.1 @babel/core:

它是Babel实现编译的核心。平时说的Babel版本指的其实就是这个core包的版本。

3.2 @babel/cli

命令行工具,以便可以通过命令行编译文件

3.3 @babel/preset-env

Babel编译ES6+语法,是通过一个个插件plugin去实现的。每年都会有不同新的提案、新的语法,但我们不可能一个个插件去配置,所以就有了preset这个东西。因此我们可以理解成preset就是一个语法插件集合包,这样我们只用安装这一个包,不需要一个个配插件,就可以很方便的编译最新的语法了。

配置方式如下:

1
2
3
4
5
6
// 修改babel.config.js
const presets = [
'@babel/preset-env'
];

module.exports = {presets};

在Babel7之后,@babel/preset-env只提供stage4阶段的提案转换,所以对于小于stage 4的提案语法,则必须先安装再手动引入对应插件。比如:

1
2
3
4
5
6
7
8
9
const presets = [
'@babel/preset-env'
];

const plugins = [
'@babel/plugin-proposal-do-expressions'
];

module.exports = {plugins, presets};

3.4 @babel/polyfill

(1)polyfill

ES6+除了提供很多简洁的语法(let、class、() => {}等)外,还为我们提供了很多便捷的API(Promise、Symbol、Array.prototype.includes等)。但旧版本浏览器是不支持这些API的,而polyfill存放了这些API的方法与实现,所以它可以使得这些不支持的浏览器,支持这些API。

polyfill也分很多种,像core-js是会提供旧版本浏览器缺失的所有的API;还有一些只提供缺失API的某块,例如 promise-polyfill、proxy-polyfill 等。

Babel配置polyfill的过程,就是实现旧版本浏览器对这些API支持的过程。

(2)@babel/polyfill

这是一个polyfill(其核心是依靠core-js@2.x.x实现)。虽然这个包已经被废弃了,但我们还是稍微了解一下它。(从Babel 7.4.0开始,这个包已经被弃用,转而直接包含core-js/stable,而stable需要core-js@3.x.x支持)

(3)@babel/polyfill由以下两个包组成:core-js@2.x.x和regenerator-runtime。

core-js:里面存放了很多ES6+ API的方法与实现。如果要在旧浏览用到Promise、Symbol、Array.prototype.includes等方法时,这个包会为我们提供。

regenerator-runtime:我们的源码里面使用了async function() {}等异步函数,或者fuction* myGenerator() {}这种Generator函数的话,就会需要用到这个包来编译。

3.5 @babel/runtime

@babel/runtime是存放了Babel辅助函数的一个集合包。当我们使用了一些ES6+的语法糖时,@babel/runtime模块会生成一些辅助函数来编译这些语法糖,并以内联的方式插入到代码中。

3.6 @babel/plugin-transform-runtime

从@babel/runtime模块我们知道,它里面存放了Babel辅助函数的集合,@babel/plugin-transform-runtime会将我们用到的辅助函数,从@babel/runtime中以require或者import的方式,引入到我们的文件中,实现复用,从而减小我们最终输出包的体积。

来源:https://juejin.cn/post/7190312484492804156

二、Babel相关配置

1、再谈core-js

core-js是一种polyfill,它提供了旧版本浏览器缺失的所有的ES6+ API的方法与实现。通过core-js来实现某个旧版本浏览器不支持的ES6+的过程叫做垫平。

2、实现Babel的第一个功能,我们用@babel/preset-env就可以了;实现Babel的第二个功能,我们需要用core-js这个包来提供polyfill,并且与@babel/preset-env或者@babel/plugin-transform-runtime的配置功能相互配置使用。

3、@babel/preset-env的主要配置项

1
2
3
4
5
6
7
8
9
10
11
12
13
// babel.config.js
const presets = [
[
'@babel/preset-env',
{
modules,
targets,
corejs,
useBuiltIns
}
]
];
module.exports = {presets};

(1)modules设置为false的话,Babel编译产生的一些辅助函数的引入方式会从require变成ES6的import from方式引入。

(2)targets:设置代码需要兼容的目标环境(浏览器),如果我们没有设置这个配置项时,Babel会假设我们要兼容的目标环境是最旧的浏览器,所以会将所有的ES6+语法代码转换为ES5。所以我们配置Babel的时候,要设置targets以减少输出代码的大小。

如果没有这个配置项时,它会去我们的Babel配置文件找顶层的targets;如果顶层没有,则去package.json中的browserslist或者根目录找.browserslistrc;如果还没有则默认为{},查找过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Babel配置文件
{
targets: 'ie 10', // 2. 如果presets里面没有设置targets,会来这里查找
presets: [
[
'@babel/preset-env',
{
targets: 'ie 9' // 1. 先在这里查找,没的话去顶层targets查找
}
]
]
}


// package.json
{
...,
browserslist: [
'ie 11' // 3. 如果顶层targest里面没有设置,会来这里查找;如果这里也没设置,则为默认值{}
]
}

(3)corejs

当useBuiltIns不为false的时候,需要设置这个配置项;

来源:https://juejin.cn/post/7197666704435920957

三、Babel官方文档阅读笔记

Babel两大功能: 新语法的转换和缺失特性的修补。

Babel官方文档