Babel是一个javascrpt编译器,能将es6转换为es5代码。并且通过插件的形式可以灵活的扩展。

从根目录读取.babelrc文件中读取配置。.babelrc是一个json文件

配置

  • plugins

    babel-plugin-transform-runtime 要和 babel-runtime配合使用 减少多余的代码
  • presets 告诉babel要转换的源代码要使用那些新的语法特性,可以分为三大类。
    • 已经被ECMAscript标准里的特性

      • ES2015
      • ES2016
      • ES2017 2017年
      • Eev 包含所有特性
    • 被社区提出但未写入ECMAscript的特性
      • babel-preset-stage-0 仅仅是个想法
      • babel-preset-stage-1 提议
      • babel-preset-stage-2 草案
      • babel-preset-stage-3 候选
      • babel-preset-stage-4 已完成
    • 一些特定功能的react,flow react需要安装babel-preset-react
  • babel垫片 Babel 几乎可以编译所有时新的 JavaScript 语法,但对于 APIs 来说却并非如此。
    • babel-runtime 前者是手动挡 主要的功能是为api提供沙箱的垫片方案,不会污染全局的api
    • babel-plugin-transform-runtime 后者是自动挡
    • babel-polyfill

      babel-polyfill则是通过改写全局prototype的方式实现,比较适合单独运行的项目。开启babel-polyfill的方式,可以直接在代码中require,或者在webpack的entry中添加,也可以在babel的env中设置useBuildins为true来开启

babel的polyfill和runtime的区别

babel-polyfill 使用场景

Babel 默认只转换新的 JavaScript 语法,而不转换新的 API。例如,Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转译。如果想使用这些新的对象和方法,必须使用 babel-polyfill,为当前环境提供一个垫片。

思考:babel-runtime 为什么适合 JavaScript 库和工具包的实现?

  1. 避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积;
  2. 在没有使用 babel-runtime 之前,库和工具包一般不会直接引入 polyfill。否则像 Promise 这样的全局对象会污染全局命名空间,这就要求库的使用者自己提供 polyfill。这些 polyfill 一般在库和工具的使用说明中会提到,比如很多库都会有要求提供 es5 的 polyfill。在使用 babel-runtime 后,库和工具只要在 package.json 中增加依赖 babel-runtime,交给 babel-runtime 去引入 polyfill 就行了;

总结:

  1. 具体项目还是需要使用 babel-polyfill,只使用 babel-runtime 的话,实例方法不能正常工作(例如 "foobar".includes("foo"))
  2. JavaScript 库和工具可以使用 babel-runtime,在实际项目中使用这些库和工具,需要该项目本身提供 polyfill

Babel 的处理步骤

Babel 的三个主要处理步骤分别是:

  • 解析(parse)
  • 转换(transform)
  • 生成(generate)

对应着babel-core源码中分别用到的babylon、babel-traverse、babel-generator

(1)Babylon

Babylon 是 Babel 的解析器。最初是 从Acorn项目fork出来的。Acorn非常快,易于使用。

import * as babylon from "babylon";

const code = `function square(n) {
return n * n;
}`; babylon.parse(code);
// Node {
// type: "File",
// start: 0,
// end: 38,
// loc: SourceLocation {...},
// program: Node {...},
// comments: [],
// tokens: [...]
// }
(2)babel-traverse

Babel Traverse(遍历)模块维护了整棵树的状态,并且负责替换、移除和添加节点。我们可以和 Babylon 一起使用来遍历和更新节点。

import * as babylon from "babylon";
import traverse from "babel-traverse"; const code = `function square(n) {
return n * n;
}`; const ast = babylon.parse(code); traverse(ast, {
enter(path) {
if (
path.node.type === "Identifier" &&
path.node.name === "n"
) {
path.node.name = "x";
}
}
});
(3)babel-generator

Babel Generator模块是 Babel 的代码生成器,它读取AST并将其转换为代码和源码映射

import * as babylon from "babylon";
import generate from "babel-generator"; const code = `function square(n) {
return n * n;
}`; const ast = babylon.parse(code); generate(ast, {}, code);
// {
// code: "...",
// map: "..."
// }

抽象语法树(AST)

ast抽象语法树在以上三个神器中都出现过,所以ast对于编译器来说至关重要。以下列举了一些ast的应用:

  • 浏览器会把js源码通过解析器转为抽象语法树,再进一步转化为字节码或直接生成机器码
  • JSLint、JSHint对代码错误或风格的检查,发现一些潜在的错误
  • IDE的错误提示、格式化、高亮、自动补全等等
  • UglifyJS
  • 代码打包工具webpack、rollup
  • CoffeeScript、TypeScript、JSX等转化为原生Javascript

自己动手写插件

基于babel-core在IDE中编写代码
引用babel-core模块进行编码方式如下:

```
const {transform,generate}=require('babel-core');
const myPlugin=require('./myPlugin'); const code = `d = a + b + c`; var es5Code = transform(code, {
plugins: [myPlugin]
})
console.log(es5Code.code);
```
ast explorer https://astexplorer.net/

编写babel插件之前先要理解抽象语法树这个概念。编译器做的事可以总结为:解析,转换,生成。具体的概念解释去看入门手册可能会更好。这里讲讲我自己的一些理解。

解析包括词法分析与语法分析。

解析过程吧。其实按我的理解(不知道这样合适不合适= =)抽象语法树跟DOM树其实很类似。词法分析有点像是把html解析成一个一个的dom节点的过程,语法分析则有点像是将dom节点描述成dom树。

转换过程是编译器最复杂逻辑最集中的地方。首先要理解“树形遍历”与“访问者模式”两个概念。

结合树形遍历来看,就是说每个访问者有进入、退出两次机会来访问一个节点。

而我们这个替换常量的插件的关键之处就是在于,访问节点时,通过识别节点为我们的目标,然后替换他的值!

bable的更多相关文章

  1. Bable实现由ES6转译为ES5

    Babel是一个广泛使用的转码器,可以将ES6代码转译为ES5代码,从而在现有环境下执行. 举例说明: 转译前(ES6格式)代码如下: let User = { name : '张三', age : ...

  2. Mac下搭建react及bable

    1.安装node 下载: https://nodejs.org/en/download/ 测试--->返回版本号即为安装成功: $ node -v $ npm -v 2.安装全局create-r ...

  3. 使用gulp和bable实现实时编译ES6代码

    这篇文章最初发表在我自己折腾的博客站点上:使用gulp和bable实现实时编译ES6代码,该博客用了一位前辈开源的源码,基于thinkjs和vuejs开发,欢迎大家来逛逛. 问题描述> 项目开发 ...

  4. webstorm bable

    一.设置npm源 1.得到原本的镜像地址 npm get registry > https://registry.npmjs.org/ 设成淘宝的 npm config set registry ...

  5. npm常用模块之bable使用

    更多npm常用模块使用请访问:npm常用模块汇总 bable这是JavaScript编译器. Babel是一个工具链,主要用于在当前和较旧的浏览器或环境中将ECMAScript 2015+代码转换为J ...

  6. BABLE 原理

    1.babel转换原理 2.主要过程 (1)babylon进行解析得到AST (2)babel-traverse插件对AST树进行遍历转译得到新的AST树 (3)babel-generator将AST ...

  7. (开发)bable - es6转码

    参考:http://www.ruanyifeng.com/blog/2016/01/babel.html Babel Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执 ...

  8. 使用 Polyfill 而不再是 bable 来实践js新特性

    现状 我们想要用ES6 语法来写 JavaScript.然而由于我们需要兼容老版本的浏览器,那些浏览器不支持 ES6,我们需要解决这个问题. 有一个标准的做法是:写 ES6 代码 → 将所有代码编译成 ...

  9. ES6模块import细节

    写在前面,目前浏览器对ES6的import支持还不是很好,需要用bable转译. ES6引入外部模块分两种情况: 1.导入外部的变量或函数等: import {firstName, lastName, ...

随机推荐

  1. 【洛谷3759】[TJOI2017] 不勤劳的图书管理员(树套树)

    点此看题面 大致题意: 给定一个序列,每个元素有两个属性\(a_i\)和\(v_i\),每次操作改变两个元素的位置,求每次操作后\(\sum{v_i+v_j}[i<j,a_i>a_j]\) ...

  2. Matlab将多幅图片保存为mat

    %% 储存某目录所有的图片 pt = 'd:\imgs\'; ext = '*.jpg'; dis = dir([pt ext]); nms = {dis.name}; for k = 1:lengt ...

  3. Web/Java Web项目如何模块化?没有正文,别点

    事情是这样的,两三年前做了几个Java Web项目,由于薪资原因,原主程都离开了. 由于公司不规范,也没有留下正规的开发文档,只有一个源程序在手里.后面的很多系统维护都很被动. 领导就觉得说,这样不好 ...

  4. nginx installl

    参考http://jingyan.baidu.com/album/4b07be3cbbb54848b380f322.html?picindex=5 安装nginx需要的依赖包 wget 下载 编译安装 ...

  5. Webpack机制、原理简单小结

    一.webpack的构成 entry  代表项目的入口 module  开发中,每一个文件可以看作一个module chunk  代码块 loader  模块转化器 plugin  扩展插件,自定义w ...

  6. Java中的异常处理从概念到实例

    1.概念 采用新的异常处理机制 在以往的程序开发过程中,经常采用返回值进行处理.例如,在编写一个方法,可以返回一个状态代码,调用者根据状态代码判定出错与否.若状态代码表示一个错误,则调用这进行相应的处 ...

  7. 第四篇、Swift_Podfile文件配置格式

    # Uncomment this line to define a global platform for your project platform :ios, '9.0' # Comment th ...

  8. 14.2-ELK 经典用法—企业自定义日志收集切割和mysql模块

    本文收录在Linux运维企业架构实战系列 一.收集切割公司自定义的日志 很多公司的日志并不是和服务默认的日志格式一致,因此,就需要我们来进行切割了. 1.需切割的日志示例 2018-02-24 11: ...

  9. 基于js原生封装的点击显示完整文字

    基于js原生封装的点击显示完整文字 (function(window) { var inner = ''; var showCont_s = function(ele) { this.init.app ...

  10. 【Python】剑指offer 14:剪绳子

    题目:给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],-,k[m].请问k[0]k[1]-*k[m]可能的最大乘积是多少 ...