每天对自己多问几个为什么,总是有着想象不到的收获。 一个菜鸟小白的成长之路(copyer)
为什么需要babel
在前端中有着很多的新语法 , 比如: ES6, TS,JSX等,他们都需要babel
的转化
所以,学习Babel
对于我们理解代码从编写到线上的转变过程至关重要
babel到底是什么呢
-
Babel是一个工具链
,主要运用于旧浏览器或者环境中将ES6代码转换为向后兼容版本的JavaScript -
包括:语法转换,源代码转换等
Babel的命令式使用
babel本身可以作为一个独立的工具,可以不用和webpack等一起使用
如果想要使用命令行babel,需要安装如下的库:
@babel/core
: babel的核心代码,必须安装@babel/cli
: 可以让我们在命令行使用babel
安装:
npm install @babel/cli @babel/core -D
使用babel来处理我们的源代码:
- src : 源文件的目录
- –out-dir: 指定要输出的文件夹dist
- –out-file: 指定输出的文件名
npx babel src --out-file dist
在目录文件夹下,新建一个demo.js
//demo.js
const message = 'james';
[1,2,3].map(n => n + 1);
执行命令
npx babel demo.js --out-file dist.js
输入结果:
const message = 'james';
[1, 2, 3].map(n => n + 1);
可以发现并没有成功把 ES6代码转成 ES5代码。
为什么呢?
因为babel也需要插件的支持
插件的使用
针对箭头函数的插件
安装
npm install @babel/plugin-transform-arrow-functions -D
运行指令
npx babel demo.js --out-file dist.js --plugins=@babel/plugin-transform-arrow-functions
就可以对箭头函数成功的转化成ES5代码了。
针对块级作用域的插件
安装:
npm install @babel/plugin-transform-block-scoping -D
运行指令
npx babel demo.js --out-file dist.js --plugins=@babel/plugin-transform-arrow-functions,@babel/plugin-transform-block-scoping
就可以成功的把 const
变成 var
但是ES6的语法太多,那就需要安装很多的插件,并且运行指令
这样拼接也是很长的。那应该怎么处理呢?
babel 的预设preset
preset里面内置了很多的ES6的插件,就不需要一个一个的安装使用了,直接安装preset就OK了
安装
npm install @babel/preset-env -D
运行指令
npx babel demo.js --out-file dist.js --presets=@babel/preset-env
效果
//还开启了严格模式
"use strict";
var message = 'james';
[1, 2, 3].map(function (n) {
return n + 1;
});
这样就可以处理大部分的ES6代码转换成ES5代码
了
babel的底层原理
我们可以把babel看成一个编译器
babel编译器的作用就是将我们的源代码
,转化成浏览器可以直接识别的另外一种源代码
babel 的编译流程:
- 解析阶段(Parsing)
- 转换阶段(Transformation)
- 生成阶段(Code Generation)
babel编译器的执行原理: (借鉴coderwhy老师的图)
详细版的就是:
简单的具体步骤的解释:
- 原生源代码 const name = “why”
- 词法分析 , 就是切割语句,形成单独的字符串
- token数组,把生成的字符串放到数组中[‘const’, ‘name’,‘=’,‘why’]
- 语法分析,找出关键词,const
- 生成AST树
- 遍历AST树
- 访问AST的每个节点
- 如果是关键词什么的,找到对应的插件(把const 转化为ES5的var)
- 生成新的AST树
- 生成转化后的浏览器能识别的源代码
babel-loader
一般来说,是在构建工具里面使用babel,比如webpack。那么就需要babel-loader的支持
安装
npm install babel-loader -D
//如果没有安装@babel/core, 也是需要安装的,这是babel的核心代码
使用:
跟上面一样,使用babel的时候,也是需要插件的。
// webpack.config.js
module.exports = {
//设置模式
mode: 'development',
//设置source-map,建立js映射文件,方便调试代码和错误
devtool: 'source-map',
//入口文件 (可以修改地址)
entry: './src/index.js',
//打包的出口文件
output: {
//打包的路径
path: path.resolve(__dirname, './build'),
//打包过后的文件名
filename: 'build.js'
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
//插件
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-arrow-functions"
]
//预设
presets: [
"@babel/preset-env" //写法一: 字符串的形式
//写法二: 数组的形式
[“@babel/preset-env”, { //对前面的插件的配置} ]
]
}
}
]
}
]
}
}
当然也可以单独的提取出来
babel的配置文件
两种形式
-
pbabel.config.json(或者.js,.cjs,.mjs)文件;
-
babelrc.json(或者.babelrc,.js,.cjs,.mjs)文件
写法跟上面是一样的
//babel.config.js
module.exports = {
presets: [
"@babel/preset-env"
]
}
//webpack.config.js
module.exports = {
//设置模式
mode: 'development',
//设置source-map,建立js映射文件,方便调试代码和错误
devtool: 'source-map',
//入口文件 (可以修改地址)
entry: './src/index.js',
//打包的出口文件
output: {
//打包的路径
path: path.resolve(__dirname, './build'),
//打包过后的文件名
filename: 'build.js'
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader'
}
]
}
]
}
}