Babel篇|博客系列
# 前期准备
学习一个新的知识, 我还是偏向于用案例的的方式来打开讲解它.
所以在正式开始阅读之前, 让我们先来准备一个这样的案例项目:
mkdir babel-basic && cd babel-basic
npm init -y
mkdir src && cd src
touch index.js
一顿操作之后, 我们新建的项目目录为:
/babel-basic
|- /src
|- index.js
|- package.json
现在package.json是最原始的配置, 而index.js暂时没有写内容.
package.json:
{
"name": "babel-basic",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {}
}
下面我都将围绕这个babel-basic项目来进行讲解, 我希望你也能在本地准备一个这样的项目案例, 以便你更好的理解我接下来要说的内容.
# @babel/core
我们学习Babel, 首先要了解一个叫@babel/core 的东西, 它是Babel的核心模块.
当然要使用它, 我们得先安装:
$ npm i --save-dev @babel/core
安装成功之后就可以在我们的代码中使用了, 你可以采用CommonJS的引用方式:
const babel = require('@babel/core');
babel.transform("code", options);
这里的知识点有很多, 不过你不用急于的掌握它, 只需要知道它是Babel的核心, 让我们接着往下看.
# @babel/cli
再然后就是@babel/cli, 它是一个终端运行工具, 内置的插件,运行你从终端使用babel的工具.
同样, 它也需要先安装:
$ npm i --save-dev @babel/cli @babel/core
让我们安装@babel/cli的同时再来安装一下@babel/core,
现在, 让我先在src/index.js中写上一段简单的代码, 并来看看它的基本用法.
src/index.js:
const fn = () => 1; // 箭头函数, 返回值为1
console.log(fn());
用法一: 命令行的形式(在项目根目录执行语句):
$ ./node_modules/.bin/babel src --out-dir lib
这段语句的意思是: 它使用我们设置的解析方式来解析src目录下的所有JS文件, 并将转换后的每个文件都输出到lib目录下.
但是注意了, 由于我们现在没有设置任何的解析方式, 所以你在执行了这段语句之后, 能看到项目中多了一个lib目录, 而且里面的JS代码和src中的是一样的. 至于我说的解析方式, 就是后面我要介绍的plugins和presets.
另外, 如果你是npm@5.2.0附带的npm包运行器的话, 就可以用npx babel来代替./node_modules/.bin/babel:
$ npx babel src --out-dir lib
用法二: 给package.json中配置一段脚本命令:
{
"name": "babel-basic",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
+ "build": "babel src -d lib"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
+ "@babel/cli": "^7.8.4",
+ "@babel/core": "^7.8.4"
}
}
现在运行npm run build效果也是一样的, -d是--out-dir的缩写…
(我们使用上面的 --out-dir 选项。你可以通过使用 --help 运行它来查看 cli 工具接受的其余选项。但对我们来说最重要的是 --plugins 和 --presets。)
$ npx babel --help
# 插件plugins
# 基本概念
知道了Babel的基本用法之后, 让我们来看看具体的代码转换.
现在要介绍的是插件plugins, 它的本质就是一个JS程序, 指示着Babel如何对代码进行转换.
所以你也可以编写自己的插件来应用你想要的任何代码转换.
# 插件案例(箭头函数插件)
但是首先让我们来学习一些基本的插件.
如果你是要将ES6+转成ES5, 可以依赖官方插件, 例如:
@babel/plugin-transform-arrow-functions:
$ cnpm i --save-dev @babel/plugin-transform-arrow-functions
$ npx babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
这个插件的作用是将箭头函数转换为ES5兼容的函数:
还记得我们之前的src/index.js吗:
const fn = () => 1; // 箭头函数, 返回值为1
console.log(fn());
现在编译之后, 你再打开lib/index.js来看看.
它是不是被转换为ES5的代码了呢? 😁
const fn = function () {
return 1;
}; // 箭头函数, 返回值为1
console.log(fn());
捣鼓了这么久, 终于看到了一点实际的效果, 此时有点小兴奋啊😄
表情包开心
虽然我们已经实现了箭头函数转换的功能, 但是ES6+其它的语法(比求幂运算符**)却并不能转换, 这是因为我们只使用了@babel/plugin-transform-arrow-functions这个功能插件, 没有使用其它的了.
# Presets:
# 基本概念
如果想要转换ES6+的其它代码为ES5, 我们可以使用"preset"来代替预先设定的一组插件, 而不是逐一添加我们想要的所有插件.
这里可以理解为一个preset就是一组插件的集合.
presets和plugins一样, 也可以创建自己的preset, 分享你需要的任何插件组合.
# @babel/preset-env
例如, 我们使用envpreset:
cnpm i --save-dev @babel/preset-env
envpreset这个preset包括支持现代JavaScript(ES6+)的所有插件.
所以也就是说你安装使用了envpreset之后, 就可以看到其它ES6+语法的转换了.
现在让我们来用用ES7中的求幂运算符和函数参数支持尾部逗号这两个功能吧:
src/index.js:
const fn = () => 1; // ES6箭头函数, 返回值为1
let num = 3 ** 2; // ES7求幂运算符
let foo = function(a, b, c, ) { // ES7参数支持尾部逗号
console.log('a:', a)
console.log('b:', b)
console.log('c:', c)
}
foo(1, 3, 4)
console.log(fn());
console.log(num);
然后在命令行里使用这个preset:
npx babel src --out-dir lib --presets=@babel/preset-env
现在打开lib/src看看:
"use strict";
var fn = function fn() {
return 1;
}; // 箭头函数, 返回值为1
var num = Math.pow(3, 2);
var foo = function foo(a, b, c) {
console.log('a:', a);
console.log('b:', b);
console.log('c:', c);
};
foo(1, 3, 4);
console.log(fn());
console.log(num);
求幂运算符被转换为成Math.pow()
函数参数的最后一个逗号也被去掉了.
截止到现在, 看完了@babel/core、@babel/cli、plugins、presets, 相信你对Babel的功能有一定了解了吧, 但是真正使用起来我们不可能都是靠命令行的形式吧, 没错, 接下来我要将这些功能做成配置项.
# 配置
上面👆介绍的都是一些终端传入CLI的方式, 在实际使用上, 我们更加偏向于配置文件.
例如我们在项目的根目录下创建一个babel.config.js文件:
const presets = [
[
"@babel/env",
{
targets: {
edge: "17",
chrome: "64",
firefox: "60",
safari: "11.1"
}
}
]
]
module.exports = { presets };
加上这个配置的作用是:
- 使用了
envpreset这个preset envpreset只会为目标浏览器中没有的功能加载转换插件
现在你要使用这个配置就很简单了, 直接用我们前面package.json配置的命令行语句:
{
"scripts": {
"build": "babel src -d lib"
}
}
执行npm run build就可以了.
这个命令行语句看起来并没有修改, 那是因为它默认会去寻找跟根目录下的一个名为babel.config.js的文件(或者babelrc.js也可以, 这个在之后的使用babel的几种方式中会说到), 所以其实就相当于以下这个配置:
{
"scripts": {
"build": "babel src -d lib --config-file ./babel.config.js"
}
}
因此如果你的Babel配置文件是babel.config.js的话, 这两种效果是一样的.
(--config-file指令就类似于webpack中的--config, 用于指定以哪个配置文件构建)
这里我重点要说一下只会为目标浏览器中没有的功能加载转换插件这句话的意思.
例如我这里配置的其中一项是edge: "17", 那就表示它转换之后的代码支持到edge17.
所以你会发现, 如果你用了我上面babel.config.js的配置之后生成的lib文件夹下的代码好像并没有发生什么改变, 也就是它并没有被转换成ES5的代码:
src/index.js:
