这里讲 babel
全家桶之间的关系。
参考资料
前情提要
babel 收到的版本变动很大,下面的版本在某些地方已经不适用了,最大的版本区别在于。
babel7
babel7
以前 npm
安装core
npm i babel-core --save-dev
babel7
以后安装 core
npm i @babel/core --save-dev
对于 .babelrc文件
@babel/preset
,@babel/plugin
不可省略,否则会当成 babel7
以下插件处理,出现无法找到插件的报错。
比如
1 | { |
配置文件
Babel
的配置文件是.babelrc
,存放在项目的根目录下。使用Babel
的第一步,就是配置这个文件。
该文件用来设置转码规则和插件,基本格式如下。
1 | { |
presets
字段设定转码规则,官方提供以下的规则集,你可以根据需要安装。
ES2015转码规则
npm install --save-dev babel-preset-es2015
react转码规则
npm install --save-dev babel-preset-react
ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-0
$ npm install --save-dev babel-preset-stage-1
$ npm install --save-dev babel-preset-stage-2
$ npm install --save-dev babel-preset-stage-3
然后,将这些规则加入.babelrc。
1 | { |
注意,以下所有Babel
工具和模块的使用,都必须先写好.babelrc
。
全家桶关系
以下的名字是 babel7
之前的方式。但是,相互之间的关系在后面的版本是不变的。
babel-core
当我们在webpack
中使用babel
的时候,首先要安装babel-core
,这是babel
编译库的核心包。
npm install babel-core --save-dev
如果是 babel-core7+ 就需要
npm install @babel/core
babel-loader
之后,webpack
中对js
文件,我们要进行编译,就需要配置,在webpack
中,你需要用到babel-loader
帮你来使用babel
npm install babel-loader --save-dev
有趣的是 babel-loader
是没有变化的,就是上面的安装方式,没有 @
所以webpack.config.js
中,你要写好下面的代码:
1 | rules: [ |
babel-present
然后我们要理解preset
这个概念,也就是在babel
编译之前,babel
需要直到你的编译规则,到底是以什么样的规范去编译。
比如说,我需要按照es6
标准编译,那么你就安装一个 babel-preset-es2015
, 同样,如果你要按照es7
来编译,那么你就安装babel-preset-es2016
:
npm install babel-preset-es2016 --save-dev
一般来说,如果你想用最新的规范做编译,直接安装babel-preset-env
就可以了,它包含了 babel-preset-es2015
, babel-preset-es2016
, and babel-preset-es2017
,等价于babel-preset-latest
,可以编译所有最新规范中的代码:
npm install babel-preset-env --save-dev
有了编译规则之后,我们继续来配置webpack
,在babel-loade
中我们可以新增配置参数:
1 | rules: [ |
到这一步,打包的时候,babel
就会自动按照最新语法规范,对我们的代码进行编译了。
Babel
也可以用于浏览器环境。但是,从Babel 6.0
开始,不再直接提供浏览器版本,而是要用构建工具构建出来。如果你没有或不想使用构建工具,可以通过安装5.x
版本的babel-core
模块获取。
那么问题来了,我们要把我们的代码编译称什么样子呢?如果是一个只要求兼容chrome
浏览器的项目,chrome
对很多es6
语法支持的很好,所以不用做很多编译,代码就可以在chrome
下运行了。如果我的项目要兼容到很低的浏览器版本,那么肯定要把es6
,7
,8
的语法编译成es4
或者es5
的语法。到底编译到什么成都,我们可以通过preset
的配置项继续设置:
1 | rules: [ |
在presets
里面,我们对babel-preset-env
增加了一个配置项叫做browser
,值是>1%
,它的意思是,让babel
做编译的时候,编译出来的语法支持所有市场占有率超过1%
的浏览器。或者你可以写成这样:
1 | rules: [ |
把参数变成chrome
,那么打包出的代码,只能保证在chrome
上运行正常,其他浏览器能不能跑就不好说了,因为你配置的打包程度就是兼容chrome
即可。
这部分的配置参数很灵活,大家可以参考官方文档继续调整:Env preset · Babel
babel-polyfill
那么接下来我们继续说babel-polyfill
是个什么东东。babel
官网上写了很明确一句话,babel
只负责对语法进行编译。当我们写尖头函数,babel
会帮你把它编译成普通函数,这没有任何问题,但是,比如说我们代码里使用了promise
,babel
打包出来的代码其实还是promise
,在低版本浏览器里,promise
并不支持,但是babel
并不会帮你处理,因为这不是语法编译层面需要做的事情。不转换新的API包括,比如Iterator
、Generator
、Set
、Maps
、Proxy
、Reflect
、Symbol
、Promise
等全局对象。
于是,如果我们要让打包出来的代码能兼容低版本浏览器,还要考虑到promise
,Set
这样的新语法低版本浏览器不兼容的问题,这时候babel-polyfill
就出场了。你只需要全局安装一下babel-polyfill
:
npm install --save-dev babel-polyfill
然后在项目中使用一下它,你的代码就不存在刚才提到的兼容性问题了。
import 'babel-polyfill'
但是,直接用babel-polyfill
会有一些坑,第一个坑是污染全局环境,比如说低版本浏览器没有Set
,但是babel-polyfill
会在全局变量里加一个Set
。再一个问题是,会造成代码冗余,举个例子,多个模块用到Promise
,每个模块里都有可能独立存在一个对Promise
做兼容性的代码。所以,使用babel-polyfill
可以解决兼容性问题,但并不是最佳方案,于是,出现了babel-plugin-transform-runtime
,使用这个插件,就可以解决上面的问题了。
babel-plugin-transform-runtime/babel-runtime
npm install --save-dev babel-plugin-transform-runtime
npm install --save babel-runtime
先安装插件,然后再安装babel-runtime
, 之后,我们改一下配置
1 | rules: [ |
增加一个plugin
的配置,好了到此,整个babel
的配置差不多了。最后我们可以在工程目录下创建一个.babelrc
文件,把关于babel
的配置放进去:
1 | { |
然后,webpack.config.js
可以精简为:
1 | rules: [ |
补充几点,一般来说,在自己写框架或者库的时候,使用babel-plugin-transform-runtime
是个很好的选择,主要是不污染环境。而如果自己写项目,不使用它,使用babel-polyfill
会更简单一些。
另外,babel-polyfill
和babel-plugin-transform-runtime
是独立的,两者没有依赖关系,不要两个一起安装,没意义~
在这里贴一下,我在 babel7+
的配置
1 | "@babel/core": "^7.12.10", |
.babelrc
的配置如下
1 | { |
其他相关说明
命令行转码babel-cli
Babel
提供 babel-cli
工具,用于命令行转码。
babel-node
babel-cli
工具自带一个babel-node
命令,提供一个支持ES6
的REPL
环境。它支持Node
的REPL
环境的所有功能,而且可以直接运行ES6
代码。
它不用单独安装,而是随babel-cli
一起安装。然后,执行babel-node
就进入PEPL
环境。