首先,先说一下babel是什么?
Babel 是一个 JavaScript 编译器。
Babel的核心包
-
babel-core: The core module that wraps everything in our transform api (used for integrations)
- babel-parser: JavaScript解析器。输出:Babel解析器根据Babel AST格式生成AST,它基于ESTree规范。
- babel-types: 作用于 AST节点的类lodash库。功能主要有两种:验证 AST 节点的类型;构建 AST 节点
- babel-template: 从string template 生成AST。计算机科学中称为准引用的实现。
- babel-traverse: 遍历AST并根据.babelrc配置处理,生成最终AST。
- babel-generator: 将AST转换为代码
- babel-helpers: Babel转换使用的辅助函数集合
- babel-code-frame: 产生错误并且能指向源代码位置
- babel-register: require的 hook。 改写node require方法,调用require时自动编译
然后再介绍一下babel的四个点
- 使用方式
- babel-core
- babel-polyfill
- plugin和preset
1.使用方式,介绍两种比较常见的方式
- 用在package.json中
- 用在.babelrc中
用在 package.json中,配置如下
"babel": {
"plugins": [
"transform-decorators-legacy"
],
"presets": [
"react-app"
]
},
用在.babelrc中,配置如下
{
"presets": [
"env",
"stage-0",
"react"
],
"plugins": ["transform-decorators-legacy"]
}
2.babel-core
如果你需要以编程的方式来使用 Babel,可以使用 babel-core 这个包
babel-core 的作用是把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,rest 参数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js。具体的实现让配置文件的插件来处理。
依赖的包如下
"@babel/parser": "^7.5.5",
"@babel/types": "^7.5.5",
"@babel/template": "^7.4.4",
"@babel/traverse": "^7.5.5",
"@babel/generator": "^7.5.5",
"@babel/code-frame": "^7.5.5",
"@babel/helpers": "^7.5.5",
- babel-parser: JavaScript解析器。输出:Babel解析器根据Babel AST格式生成AST,它基于ESTree规范。
- babel-types: 作用于 AST节点的类lodash库。功能主要有两种:验证 AST 节点的类型;构建 AST 节点
- babel-template: 从string template 生成AST。计算机科学中称为准引用的实现。
- babel-traverse: 遍历AST并根据.babelrc配置处理,生成最终AST。
- babel-generator: 将AST转换为代码
- babel-helpers: Babel转换使用的辅助函数集合
- babel-code-frame: 产生错误并且能指向源代码位置
作用就是根据.babelrc(配置文件)转换代码,主要作用如下:
- 加载和处理配置(config)
- 加载插件
- 调用 Parser 解析生成 AST
- 调用 Traverser 遍历AST并根据.babelrc配置处理,生成最终AST
- 调用Generator 将AST转换为代码
- 生成代码,包括SourceMap转换和源代码生成
3.babel-polyfill
作用是在旧版本浏览器中提供对新的 JavaScript 特性和 API 的支持
babel预设可以编译几乎所有的JavaScript新语法,但是对于API却不能解决(内置对象比如 Promise,静态方法比如 Array.from 或者 Object.assign,实例方法比如 Array.prototype.includes 和生成器函数),解决这个问题babel用的是 babel-polyfill。
Webpack 中使用babel-polyfill
在 webpack.config.js 中,将 babel-polyfill 加到你的 entry 数组中:
module.exports = {
entry: ["babel-polyfill", "./app/js"]
};
babel v7.4版之后,@babel/polyfill已经被废弃。使用@babel/preset-env
@babel/preset-env是一个智能预设,允许您使用最新的JavaScript,而无需微观管理目标环境需要哪些语法转换(以及可选的浏览器polyfill)。
.babelrc文件
{
"presets": [
["@babel/preset-env",{
"useBuiltIns":"usage"
}],
"@babel/preset-react"
]
}
# useBuiltIns配置值:usage、entry
# usage:按需导入,并且只导入一次
# entry: 入口处一次全部导入
4.plugin和preset
plugin/preset的排序
- Plugin 会运行在 Preset 之前。
- Plugin 会从第一个开始顺序执行。ordering is first to last.
- Preset 的顺序则刚好相反(从最后一个逆序执行)。
preset 的逆向顺序主要是为了保证向后兼容,因为大多数用户的编写顺序是 ['es2015', 'stage-0']。这样必须先执行 stage-0 才能确保 babel 不报错。因为低一级的 stage 会包含所有高级 stage 的内容
Plugin/Preset 路径
如果 plugin 是通过 npm 安装,你可以传入 plugin 名字给 babel,babel 将检查它是否安装在 node_modules 中
"plugins": ["babel-plugin-myPlugin"]
你也可以指定你的 plugin/preset 的相对或绝对路径。
"plugins": ["./node_modules/asdf/plugin"]
Plugin/Preset 简写
如果你使用 babel-plugin- 作为 plugin 的前缀,你可以使用简写的形式省略掉该前缀。
"plugins": ["myPlugin"] preset 与之相同
"presets": ["babel-preset-myPreset"]
vs
"presets": ["myPreset"]
这也适用于包裹作用域:
"presets": ["@org/babel-preset-name"]
简写:
"presets": ["@org/name"]
presets
presets属性告诉Babel要转换的源码使用了哪些新的语法特性,presets是一组Plugins的集合
babel-preset-es2015: 可以将es6的代码编译成es5.
babel-preset-es2016: 可以将es7的代码编译为es6.
babel-preset-es2017: 可以将es8的代码编译为es7.
babel-preset-latest: 支持现有所有ECMAScript版本的新特性。
babel-preset-env 出现了,它的功能类似于 babel-preset-latest,它会根据目标环境选择不支持的新特性来转译。