Babel是一个工具链,主要用于将ECMAScript 2015+版本代码向后兼容 Javascript 语法,以即可以运行到旧版本浏览器或其余环境中。html
做为一种语言,JavaScript在不断发展,新的标准/提案和新的特性层出不穷。在获得普遍普及以前,Babel可以让你提早(甚至数年)使用他们。node
Babel 的三个主要处理步骤分别是: 解析(parse),转换(transform),生成(generate)。react
将代码解析成抽象语法树(AST),每一个js引擎(好比Chrome浏览器中的V8引擎)都有本身的AST解析器,而Babel是经过Babylon实现的。在解析过程当中有两个阶段:词法分析和语法分析,词法分析阶段把字符串形式的代码转换为令牌(tokens)流,令牌相似于AST中节点;而语法分析阶段则会把一个令牌流转换成 AST的形式,同时这个阶段会把令牌中的信息转换成AST的表述结构。es6
在这个阶段,Babel接受获得AST并经过babel-traverse对其进行深度优先遍历,在此过程当中对节点进行添加、更新及移除操做。这部分也是Babel插件介入工做的部分。npm
例如,Babel可以将新的ES2015箭头函数语法:json
const square = n => n * n;
复制代码
转译为:gulp
const square = function square(n) {
return n * n;
}
复制代码
babel的核心模块,包括一些核心api例如:transform。api
/*
* @param {string} code 要转译的代码字符串
* @param {object} options 可选,配置项
* @return {object}
*/
babel.transform(code: string, options?: Object)
//返回一个对象(主要包括三个部分):
{
generated code, //生成码
sources map, //源映射
AST //即abstract syntax tree,抽象语法树
}
复制代码
更多AST知识点浏览器
一些使用babel插件的打包或构建工具都有使用到这个方法,下面是一些引入babel插件中的源码:bash
//gulp-babel
const babel = require('babel-core');
/*
some codes...
*/
module.exports = function (opts) {
opts = opts || {};
return through.obj(function (file, enc, cb) {
try {
const fileOpts = Object.assign({}, opts, {
filename: file.path,
filenameRelative: file.relative,
sourceMap: Boolean(file.sourceMap),
sourceFileName: file.relative,
sourceMapTarget: file.relative
});
const res = babel.transform(file.contents.toString(), fileOpts);
if (res !== null) {
//some codes
}
} catch (err) {
//some codes
}
}
}
//babel-loader
var babel = require("babel-core");
/*
some codes...
*/
var transpile = function transpile(source, options) {
//some code
try {
result = babel.transform(source, options);
} catch (error) {
//some codes
}
//some codes
}
//rollup-pugin-babel
import { buildExternalHelpers, transform } from 'babel-core';
/*
some codes...
*/
export default function babel ( options ) {
//some codes
return {
// some methods
transform ( code, id ) {
const transformed = transform( code, localOpts );
//some codes
return {
code: transformed.code,
map: transformed.map
};
}
}
}
复制代码
Babel的CLI是一种在命令行下使用Babel编译文件的简单方法。主要用于文件的输入输出。
全局安装
npm install -g babel-cli
复制代码
咱们能够这样编译咱们第一个文件:
babel test.js
//编译后的文件输出在终端
复制代码
babel test.js -o test-out.js
//编译后的文件输出在test-out.js文件中
复制代码
尽管能够把Babel CLI全局安装在你的机器上,可是按项目逐个安装在本地会更好。 有两个主要的缘由。
将Babel CLI安装到本地能够运行:
npm install --save-dev babel-cli
复制代码
如今能够不直接在命令行运行Babel了,取而代之咱们将命令写在package.json的script里。
只需将"scirpts"字段添加到你的package.json文件内。
{
"scripts":{
"build": "babel src -d lib",
...
},
...
}
复制代码
如今能够在终端里运行:
npm run build
复制代码
这将以与以前一样的方式运行Babel。
babel-node是随babel-cli一块儿安装的,只要安装了babel-cli就会自带babel-node。 在命令行输入babel-node会启动一个REPL(Read-Eval-Print-Loop),这是一个支持ES6的js执行环境。
babel-register字面意思能看出来,这是babel的一个注册器,它在底层改写了node的require方法,引入babel-register以后全部require并以.es6, .es, .jsx 和 .js为后缀的模块都会通过babel的转译。
//test.js
const name = 'test';
module.exports = () => {
const json = {name};
return json;
};
//main.js
require('babel-register');
var test = require('./test.js'); //test.js中的es6语法将被转译成es5
console.log(test.toString()); //经过toString方法,看看控制台输出的函数是否被转译
/*
function () {
var json = { name: name };
return json;
}
*/
复制代码
babel-polyfill在代码中的做用主要是用已经存在的语法和api实现一些浏览器尚未实现的api,对浏览器的一些缺陷作一些修补。例如Array新增了includes方法,我想使用,可是低版本的浏览器上没有,引入babel-polyfill则帮咱们添加了这些方法。
babel全部的操做基本都会来读取这个配置文件,除了一些在回调函数中设置options参数的,若是没有这个配置文件,会从package.json文件的babel属性中读取配置。
babel中的插件,经过配置不一样的插件才能告诉babel,咱们的代码中有哪些是须要转译的。
预设就是一系列插件的集合,就好像修图同样,把上次修图的一些参数保存为一个预设,下次就能直接使用。
// cnpm install -D babel-preset -env
{
"presets": [
["env", {
"targets": { //指定要转译到哪一个环境
//浏览器环境
"browsers": ["last 2 versions", "safari >= 7"],
//node环境
"node": "6.10", //"current" 使用当前版本的node
},
//是否将ES6的模块化语法转译成其余类型
//参数:"amd" | "umd" | "systemjs" | "commonjs" | false,默认为'commonjs'
"modules": 'commonjs',
//是否进行debug操做,会在控制台打印出全部插件中的log,已经插件的版本
"debug": false,
//强制开启某些模块,默认为[]
"include": ["transform-es2015-arrow-functions"],
//禁用某些模块,默认为[]
"exclude": ["transform-es2015-for-of"],
//是否自动引入polyfill,开启此选项必须保证已经安装了babel-polyfill
//参数:Boolean,默认为false.
"useBuiltIns": false
}]
]
}
复制代码
关于最后一个参数useBuiltIns,有两点必需要注意:
经过scirpt标签type属性传入"text/babel",在浏览器中进行高级语法向低级语法的转换。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
const PI = "3.14";
ReactDOM.render(<h1>hi</h1>,document.getElementById("app"))
</script>
</body>
</html>
复制代码