本教程是针对新人的入门级教程。教程参考了官方文档。
源码github:https://github.com/pengfeiw/babel-tutorial
假设你已经安装了node、npm(或yarn)等必要的开发环境。
Babel是JavaScript的编译器,我认为编译器这个词用于描述Babel不是很准确,因为JavaScript并不像C++、C#那样需要预先编译才能运行,JavaScript是一门解释型语言,Babel的作用是将ECMAScript 2015+的代码转换为旧的浏览器可兼容的代码,所以它是一个代码转换器,将新语法转换成旧的语法,这样以使新的项目可以在老版本的浏览器环境上执行。
Babel的主要作用如下:
例如使用Babel,可以将箭头函数转换成普通函数。
// Babel输入: ES2015的箭头函数
[1, 2, 3].map(n => n + 1);
// Babel输出: ES5等价的语法
[1, 2, 3].map(function(n) {
return n + 1;
});
所有Babel的包都发布在npm上,并且名称以@babel
为前缀(自从版本7.0之后)。接下来,我们一起看下@babel/core
和@babel/cli
这两个包。
@babel/core
#core,中文意思即核心。封装了Babel的核心功能。可已通过npm或yarn进行安装。
npm install --save-dev @babel/core
yarn add @babel/core --dev
通过以上命令将@babel/core
安装到开发依赖中,因为生产环境不需要@babel/core
,@babel/core
的主要功能是转换代码(编译代码)。
安装后,我们可以在js代码中,直接引入babel模块用于转换代码。
const babel = require("@babel/core");
babel.transformSync("code", optionsObject);
transformSync
函数的第一个参数是需要转换的代码,第二个参数为可选参数,用于设定babel的配置(configuration)。
@babel/cli
#CLI全称为Command Line Interface,即命令行接口、命令行界面。借助@babel/cli
,我们可以在命令行使用babel。
通过yarn或者npm安装@babel/cli
:
npm install --save-dev @babel/cli
or
yarn add @babel/cli --dev
安装后,可以通过命令行编译代码:
./node_modules/.bin/babel src --out-dir lib
该命令调用的是./node_modules/.bin
文件加下的babel
脚本,通过脚本运行babel,编译代码,src
为源码路径,--out-dir
选项设置输出目录为lib
。编译成功输出如下信息。
我们使用了--out-dir
配置选项设置了输出目录,@babel/cli
还支持其他的配置选项,可以通过--help
查看其他可配置的选项。
./node_modules/.bin/babel --help
执行命令后,会输出一个options列表,列表中是CLI所有可配置选项,但是目前我们只关心两个最重要的配置选项--plugins
和--presets
(插件和预定义配置)。
插件(plugins)是一段javascript程序,用于指示babel如何转换代码,你可以自己编写插件,也可以使用别人写好的插件。例如官方插件@babel/plugin-transform-arrow-functions
,用于将ES2015+的箭头函数转换为function
关键字形式的函数。
安装@babel/plugin-transform-arrow-functions
:
npm install --save-dev @babel/plugin-transform-arrow-functions
or
yarn add @babel/plugin-transform-arrow-functions --dev
使用--plugins
配置选项,设置使用@babel/plugin-transform-arrow-functions
进行编译:
./node_modules/.bin/babel src --out-dir lib --plugins=@babel/plugin-transform-arrow-functions
执行命令后,你的源码中所有的箭头函数都会被转换为function
关键字定义的函数:
const fn = () => 1;
// converted to
var fn = function fn() {
return 1;
};
很好,我们已经知道插件是什么了,并且知道如何配置使用插件了,很不错。但是如果有很多插件呢,每个都添加在命令行中岂不是很麻烦。幸运的是CLI提供了--presets
选项,可以将多个插件组合起来。
与插件相同,你可以自己创建一个预定义配置用于分享插件组合的配置。
官方早已为我们提供了@babel/preset-env
这个预定义配置。
通过以下命令安装:
npm install --save-dev @babel/preset-env
or
yar add @babel/preset-env --dev
通过--presets
选项指定使用预定义配置。
./node_modules/.bin/babel src --out-dir lib --presets=@babel/env
不需要我们设置其他的配置了,@babel/env
包含了支持所有现代JavaScript(ES2015、ES2016等)的插件。预定义配置也支持选项配置,通过配置文件设置预定义配置的选项。
首先,在项目目录下创建一个babel.config.json
文件(需要v7.8.0
和更高版本),并且添加如下内容:
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
}
}
]
]
}
通过该配置文件,@babel/env
将会只针对json文件中配置的targets
的浏览器加载插件,如果某个现代JavaScript(ES2015、ES2016等)的语法在目标浏览器中不支持,执行babel转换时,将会加载对应的插件用于转换。
我一直不知道如何翻译Polyfill
这个单词,fill是填充的意思。poly在有道词典上的意思如下:
poly
n. (非正式)理工院校,工艺专科学校(polytechnic 的简称);聚乙烯(polythene 的简称);涤纶,聚酯纤维(polyester 的简称)
MDN术语表上的解释是:
Polyfill 是一块代码(通常是 Web 上的 JavaScript),用来为旧浏览器提供它没有原生支持的较新的功能。
我就将其翻译为预填充吧,主要作用是某些比较新的语法,浏览器还未来的及支持,使用预填充,可以让开发者不必考虑浏览器是否已经支持而直接使用新的语法。这里的语法与箭头函数和function关键字函数这种语法不一样,它指的是“功能”,例如Promise
、WeakMap
、Array.from
或者Object.assign
等等。
我记得有一次项目,QQ浏览器不支持String.prototype.replaceAll
方法,导致项目在QQ浏览器上运行出错,如果使用预填充功能,应该就可以解决问题。(感兴趣的朋友可以试试,目前QQ浏览器是否支持String.prototype.replaceAll
方法)。
安装:
npm install --save @babel/polyfill
or
yarn add @babel/polyfill
注意:
--save
选项 这里是安装到生产依赖中的,不是开发依赖(细心一点)。
安装完成后,打开node_modules/@babel/polyfill/package.json
文件,可以看到dependencies
中有一个core-js
包。
core-js是一个现代javascript语法库,@babel/polyfill就是利用core-js
进行预填充的,你也可以直接从core-js
中引入你需要的功能。
env
预定义配置有一个"useBuiltIns"
选项,如果设置为"usage"
将会使用最新的功能进行预填充,在需要某个功能的模块文件里,会引入相应的功能。
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage"
}
]
]
}
假设你有如下代码:
Promise.resolve().finally();
使用babel转换后的代码如下:
"use strict";
require("core-js/modules/es7.promise.finally.js");
Promise.resolve().finally();
如果你没有设置"useBuiltIns": "usage"
,你需要设置"useBuiltIns": "entry"
,这样编译后的文件会在入口文件引入功能模块,如果不设置"useBuiltIns"
选项,编译后的文件将不会引入任何新功能模块。
(完)