-
Notifications
You must be signed in to change notification settings - Fork 20
Description
概述
Babel是一个编译器。ECMAScript每年都会推出新的规范,为JavaScript带来新的特性。但是并不是所有浏览器都能及时实现这些新的特性。所以当我们想要享受使用JavaScript新特性而又不受限于浏览器的更新速度的时候,babel可以帮到我们。它可以把ES5+版本编译为ES5版本,从而让浏览器可以正常运行。
ES5+:
[1, 2, 3].map(n => n ** 2);
ES5:
[1, 2, 3].map(function (n) {
return Math.pow(n, 2)
})
总结功能
- JavaScript的编译器
- 让JavaScript可以支持最新的语法,且不用担心兼容性
- 支持JSX和React
- 支持Flow和TypeScript的类型注解
- 支持拓展插件
- 支持调试
- 支持修改代码,已经被社区广泛使用,比如eslint对代码错误或风格的检查,IDE的错误提示、格式化、高亮、自动补全,UglifyJS压缩代码,webpack打包构建
与webpack的关系
webpack可以说是一个构建工具,它可以装配很多的插件或者编译器(loaders),babel是其中的一种转译器。
通过webpack构建项目,我们可以在打包JavaScript代码的时候,使用babel(babel-loader)把JavaScript新特性转换到JavaScript低版本可以理解的兼容模式。
babel编译过程
转译分为三个阶段:
- parsing,把代码解析成AST
- transforming,使用插件处理AST
- generating,把处理过的AST转化为最终的代码
polyfill
是对JavaScript新特性的补充。比如当我们需要把ES6转换为ES5的时候,ES6中的新对象和新API在ES5中是不存在的,那么运行的时候就会报错。
所以我们需要polyfill来补充新的对象和新的API,才能让代码在ES5环境中正常运行。
plugins
插件对于整个编译过程来说是重头戏,在第二步的使用需要使用插件去处理AST语法树。
插件不仅可以把ES6转化为ES5,还可以做很多别的事,只有想不到。
比如React就是通过插件支持JSX语法的。
presets
Presets 是可共享的 .babelrc 配置,也可以认为是一个 babel 插件的数组。
preset 和 plugin差别在于,preset的执行顺序是倒着的,plugin的执行顺序是正的。且Plugin 会运行在 Preset 之前。
官方预设了一些插件集:
babel-preset-env 相当于 es2015 ,es2016 ,es2017 及最新版本。
还有:babel-preset-20XX,babel-preset-react,babel-preset-flow
Plugin 会运行在 Preset 之前。Plugin 的执行顺序是从前往后,Preset 刚好相反。
配置
我们可以通过执行指令的时候传入一些配置,也可以通过.babelrc写好预设的配置。
Babel 会在正在被转录的文件的当前目录中查找一个 .babelrc 文件。 如果不存在,它会遍历目录树,直到找到一个 .babelrc 文件,或一个 package.json 文件中有 "babel": {} 。
配置Babel
Babel支持的配置方式有:
babel.config.js
module.exports = function (api) {
api.cache(true);
const presets = [ ... ];
const plugins = [ ... ];
return {
presets,
plugins
};
}.babelrc
{
"presets": [...],
"plugins": [...]
}package.json
{
"name": "my-package",
"version": "1.0.0",
"babel": {
"presets": [ ... ],
"plugins": [ ... ],
}
}.babelrc.js
const presets = [ ... ];
const plugins = [ ... ];
module.exports = { presets, plugins };常用options字段
- env:指定在不同环境下使用的配置。比如production和development两个环境使用不同的配置,就可以通过这个字段来配置。env字段的从process.env.BABEL_ENV获取,如果BABEL_ENV不存在,则从process.env.NODE_ENV获取,如果NODE_ENV还是不存在,则取默认值"development"
- plugins:要加载和使用的插件列表,插件名前的babel-plugin-可省略;plugin列表按从头到尾的顺序运行
- presets:要加载和使用的preset列表,preset名前的babel-preset-可省略;presets列表的preset按从尾到头的逆序运行(为了兼容用户使用习惯)
Babel运作方式
Babel 6.x
支持如下配置:
const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
},
],
];
module.exports = { presets };那么会在代码运行之前导入@babel/polyfill,用以支持新特性。
当然还可以使用useBuiltIns优化:
const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1",
},
useBuiltIns: "usage",
},
],
];
module.exports = { presets };会把代码:
Promise.resolve().finally();转化为:
require("core-js/modules/es.promise.finally");
Promise.resolve().finally();如果不使用useBuiltIns: "usage",我们将不得不把整个polyfill文件(@babel/polyfill)放在所有代码的前面。
Babel 7.x
Babel有所不同,会在代码运行之前导入如下:
import "core-js/shim"; // included < Stage 4 proposals
import "regenerator-runtime/runtime";参考
官方文档
Babel中文文档
你真的会用 Babel 吗?
【JavaScript】深入理解Babel原理及其使用
Babel 用户手册
Babel 插件手册