yinuoqingqin 2019-12-07
如何写好.babelrc?Babel的presets和plugins配置解析
Babel is a JavaScript compiler.——顾名思义,Babel
就是将最新的 ES6+
语法,向后兼容,编译转化为支持各个浏览器可以运行的 javascript
代码。
Babel
编译Babel
编译经历三个阶段:解析(parse)
,转换(transform
),生成(generate
)。
注意:在升级 Babel 6.X
版本以后,所有的插件都是可插拔的(意味着transform
流程全部交给了插件去做。)。
这就意味着安装Babel
之后,是不能工作的,需要配置对应的 .babelrc
文件才能发挥完整的作用。
如果想要通过Babel
完成你的代码转换,那么需要配置一些你需要的插件。
plugin
plugin
就是将高级的语法转化为兼容多种浏览器的载体:
Babel
构建在插件之上,使用现有的或者自己编写的插件可以组成一个转换通道,Babel
的插件分为两种: 语法插件和转换插件。
这些插件只允许 Babel
解析(parse) 特定类型的语法(不是转换)
将不识别的新内置函数进行转换:转换插件会启用相应的语法插件(因此不需要同时指定这两种插件)。
在.babelrc
设置:
{ "presets": ["@babel/plugin-transform-arrow-functions"] }
转换 => 生成:
// 转换前 const name = ‘houfee‘ let hello = `hello ${name}` let func = () => { console.log(‘转化箭头函数‘) } // 转换后 const name = ‘houfee‘; let hello = `hello ${name}`; let func = function () { console.log(‘转化箭头函数‘); };
可见,以上转换只转换了箭头函数,而const
和 let
却没有转化。
preset
Babel
将 ES6+
新语法向后兼容时,将新语法封装为多个插件转化,而不是唯一一个插件。这是你想要体验 ES6
所有的新特性(注意:语法转换只是将高版本的语法转换成低版本的,但是新的内置函数、实例方法无法转换。)时,那么你只需在.babelrc
设置:
{ "presets": ["@babel/preset-env"] }
转换 => 生成:
// 转换前 const name = ‘houfee‘ let hello = `hello ${name}` let func = () => { console.log(‘转化箭头函数‘) } class Point { constructor(x, y) { this.x = x; this.y = y; } } let promise = new Promise((res, rej) => console.log(res, rej)) // 转换后 "use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var name = ‘houfee‘; var hello = "hello ".concat(name); var func = function func() { console.log(‘转化箭头函数‘); }; var Point = function Point(x, y) { _classCallCheck(this, Point); this.x = x; this.y = y; }; var promise = new Promise(function (res, rej) { return console.log(res, rej); });
可见: @babel/preset-env
插件只是转换了已存在的语法,对于新增的内置函数依然是无法转换的。
plugin
和 preset
关系plugin
插件功能单一,只能完成特定语法转换;——特点是:颗粒度小,效率高,但是需要逐个引入(Babel
的插件有20+)。
preset
将一系列的 plugin
功能集合在一起;——特点是:一次引入多个语法功能的插件,优化配置。
plugin
和 preset
的执行顺序多个plugin
和preset
时执行顺序非常重要:
1,先执行完所有plugin
,再执行preset
。
2,多个plugin
,按照声明次序顺序执行。
3,多个preset
,按照声明次序逆序执行。
Babel
相关模块简要说明Babel
的模块那么多,那么要怎么学习呢?
目前 Babel
版本为 Babel 7.4.0
,此图只是示意(网图~)。
@babel/core
Babel
的核心 api
都在这个模块中。也就是这个模块会把我们写的 js
代码抽象成 AST
(abstract syntax tree
)树;然后再将 plugins
转译好的内容解析为 js
代码。
@babel/cli
Babel
提供的命令行工具,主要是提供 Babel
这个命令,适合安装在项目里。
@babel/node
提供了 babel-node
命令,但是 @babel/node
更适合全局安装,不适合安装在项目里。
npm install --save-dev @babel/core @babel/cli
@babel/preset-env
将新增的ES6
语法转换为浏览器支持的语法,但是不会转换新增的内置函数。
@babel/polyfill
Babel
对一些新的 API 是无法转换,比如 Generator、Set、Proxy、Promise
等全局对象,以及新增的一些方法:includes、Array.form
等。所以这个时候就需要一些工具来为浏览器做这个兼容。
官网的定义:babel-polyfill
是为了模拟一个完整的 ES6+
环境,旨在用于应用程序而不是库/工具。
@babel/polyfill
主要有两个缺点:
使用 @babel/polyfill
会导致打出来的包非常大,很多其实没有用到,对资源来说是一种浪费。
@babel/polyfill
可能会污染全局变量,给很多类的原型链上都作了修改,这就有不可控的因素存在。
因为上面两个问题,在 Babel7
通过设置 "useBuiltIns":"usage"
这个参数值就可以实现按需加载。
@babel/plugin-transform-runtime
配合其他插件使用,避免编译后的代码中出现重复的帮助程序,有效减少包体积。
@babel/preset-flow
@babel/preset-react
@babel/preset-typescript