背景
- ES6为Javascript添加了诸多强大的语法但是由于浏览器版本更新较慢这些语法再很多浏览器上是不支持的。
- nodeJs的流行使编译这个词在前端领域不在那么陌生。
基于以上两点Babel诞生了,Babel借助进NodeJs操作文件的能力将ES6版本的Js语法转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
工具包
Babel将ES6代码转化为AST(抽象语法树),然后经过一系列的插件转化为新的AST最终再将AST转化为目标代码
Babel是一个工具链,由多个工具包组成。
@babel/core
babel的核心模块包含了代码到AST及AST到代码的转换函数。但是babel/core本身不具备ES6到ES5的转换功能
@babel/cli
bable的命令行工具,让我们可以从命令行输入bable解析代码,如下
npm install @babel/core @babel/cli --save-d
输入npx babel index.js 就会输出以下代码,也可以指定输出路径如npx babel src --out-dir ./lib。我们看到输出代码依然是ES6。想要转换特定的ES6语法就就需要插件出场了。
插件(@babel/plugin-transform-xx)
安装插件并重新编译代码如下其中plugins支持使用npm包和相对路径方式(放在本地的自定义插件)。
npm install --save-dev @babel/plugin-transform-classes
.babelrc
编译后:
Bable提供了包含ES6/Modules/Experimental几个分类几十个插件转换不同的语法,我们想用一个语法都添加一个插件配置是非常麻烦的,索性Babel自带看很多预设(一些插件集合),社区也有人贡献了不同的预设,我们使用起来就比较方便了。
Presets(预设)
Presets是一系列插件的集合例如如下自定义预设及可以转化Class和箭头函数
module.exports = function() {
return {
plugins: [
"@babel/transform-classes",
"@babel/transform-classes",
]
};
}
官方提供一些默认映射如@babel/preset-env @babel/preset-typescript @babel/preset-react。注意babel-preset-stage-x已经不推荐使用了
例如 @babel/preset-react包含以下插件集合
-
@babel/plugin-syntax-jsx
-
@babel/plugin-transform-react-jsx
-
@babel/plugin-transform-react-display-name
而@babel/preset-env可以通过配置的方式生成Babel插件列表
npm install --save-dev @babel/preset-env
还可以配置目标代码为支持市场占有率大于百分比的浏览器
.babelrc
需要注意的是以上插件和预设只编译语法,对新方法和新的原生对象是不起作用的如下const被编译成了var 但是arr.includes方法没有被转移。此时就需要引入Polyfill
源码:
编译后:
Polyfill
@babel/polyfill
npm install --save @babel/polyfill
源码:
编译后:
这样就可以在低版本浏览器运行了(当使用了webpack等模块化打包工具时require会被转义成对应的模块化引入方式),需要注意的是@babel/polyfill是运行时需要的代码所有需要在源码中引入,但是@babel/polyfill压缩后大概100k,但是实际种我们可能只需要几种Polyfill,如何做到按需引入呢?
还是@babel/preset-env, 设置useBuiltIns为usage,Babel仅仅把需要的 polyfill 包含进来。
npm install --save core-js@3
.babelrc
源码:
编译后:
这样打包完的代码体积明显小了很多,但是问题是如果多个文件共同使用的一个es6特性,那么针对这个es特性的babel辅助函数会被打包到各个文件,这样文件越多包大小越大。
为了解决这个问题我们就需要引入@babel/plugin-transform-runtime插件。
使用@babel/plugin-transform-runtime时必须同时安装@babel/runtime。注意@babel/runtime时运行时逻辑
npm i @babel/plugin-transform-runtime --save-d npm i @babel/runtime–save
.babelrc
源码:
编译后:
通过安装以上两个插件辅助函数就会去@babel/runtime中加载,不会被注入各个文件。
配置
babel支持多种配置方式除了上面用到的.babelrc还有babel.config.js、.babelrc.js、直接内敛package.json
babel.config.js
.babelrc.js
package.json