从前,一提到新东西,我的反应就是兼容性好不好,如果不能满足产品经理的需求,就还是用保守的方式实现吧。毕竟前端开发是一件很灵活的事,怎么写都行,至于为何会用某种方法,一定是综合考虑兼容性,性能,用户体验,开发成本等因素后再说。兼容性和新事物有时就像鱼和熊掌不可兼得,必须权衡利弊,做一个决断。但是ECMAScript 2015不一定要等所有浏览器都支持后才可以用,于是你会想到一个工具babel,它可以助ECMAScript 2015一臂之力,让处于某个stage的且尚未纳入es规范的特性提前支持,因为babel能够把不同stage的es,转成浏览器识别的js。
在学babel前,我有一个这样的疑问,为啥说到babel,一般会提到es5+?他俩有啥关系?babel是伴随ECMAScript 2015出现的吗?如果不是,它比ECMAScript 2015出生早,还是晚呢?感觉问题很多,就像破案一样,疑点重重,越走越深,但是主方向不会忘。我有时会问自己,我是搞清它的历史背景呢,还是赶紧敲命令行,立刻做项目?内心的躁动告诉我,反正有时间研究,索性我就挖地三尺,弄清babel的祖坟在哪儿。
看了babel的官方文档后,我恍然大悟,原来babel不是TC39的作品啊!!!如果说ECMAScript的爹娘是TC39,那么babel的爹是james kyle,一个澳大利亚工程师,曾就职于Facebook。总之,babel和ECMAScript 2015没有什么血缘关系,babel也不是ECMAScript 2015出生的附属品,babel5.0发布的比ECMAScript 2015早。

一、babel版本有哪些?
2015年1月12日,6to5和esnext开源;
2015年2月15日,6to5重命名为babel;
2015年3月31日,babel 5.0发布;
2015年10月30日,babel 6.0发布。

二、babel的用途
babel是一个JavaScript编译器。
1、ES6转成ES5
默认情况下,babel自带了一组ES2015语法转化器,这些转化器能把ES2015转为ES5,让你现在就使用最新的JavaScript语法,而不用等待浏览器提供支持。在babel中,默认启用stage-2及以上的proposal。如果有人说“不同stage的babel”,这种说法是错误的,因为babel没有所谓的stage,babel就是一个编译器。至于babel的配置文件参数中为什么会牵扯到stage,是由于babel要知道把哪个stage的es5+转换成浏览器能识别的js,而TC39 Process会告诉babel是哪个stage。
2、jsx文件转成js文件
babel可以把React的JSX语法转成普通JavaScript语法。
3、babel由插件组成,可组合拼装。
4、babel支持source map,帮助调试。

三、babel的工作原理
1、解析
用babylon对源代码(比如ES6)进行词法解析,得到AST;
2、转换
用babel-traverse对AST树进行遍历转换,得到新的AST树;
3、生成
用babel-generator通过AST树生成目标代码(比如ES5)。

四、babel的配置
babel的配置文件是.babelrc,存放在项目的根目录下。使用babel的第一步,就是配置这个文件。什么是.babelrc文件呢?熟悉linux的同学一定知道,rc结尾的文件通常代表运行时自动加载的文件,配置等等,类似bashrc,zshrc。同样babelrc在这里也是有同样的作用,而且在babel6中,这个文件必不可少。
该文件用来设置转码规则和插件,基本格式如下。

{
  "presets": [],
  "plugins": []
}

1、转码规则
presets字段设定转码规则,转码规则可以告诉babel去处理什么语法。

A、babel-preset-es2015
这是ES2015(最新版本的JavaScript标准,也叫做ES6)的转码规则。使用它后,babel可以将ES6语法转码为普通 JavaScript(即ES5)语法。

# 安装ES2015转码规则
$ npm install --save-dev babel-preset-es2015

B、babel-preset-react
这是react的转码规则。使用它后,babel可以将react语法转码为普通JavaScript语法。

# 安装react转码规则
$ npm install --save-dev babel-preset-react

C、babel-preset-stage-x
这是ES7不同阶段语法提案的转码规则。使用它后,babel可以将ES7不同阶段语法转码为普通JavaScript语法。

# 安装ES7不同阶段语法提案的转码规则(共有4个阶段),选装一个
$ npm install --save-dev babel-preset-stage-
$ npm install --save-dev babel-preset-stage-
$ npm install --save-dev babel-preset-stage-
$ npm install --save-dev babel-preset-stage-

以上每种预设都依赖于紧随的后期阶段预设。例如,babel-preset-stage-1依赖babel-preset-stage-2,后者又依赖babel-preset-stage-3。
最终,在.babelrc文件这样写。

{
  "presets": [
    "es2015",
    "stage-0"
  ],
  "plugins": []
}

D、babel-preset-env
这是最新的预设插件,包含es2015,es2016,es2017和latest等,不包含react,polyfill。

$ npm install --save-dev babel-preset-env

最终,在.babelrc文件这样写,是不是比上面简洁了很多?

{
  "presets": ["env"],
  "plugins": []
}

如果与webpack一起使用,需要再配置下webpack.config.js文件。

module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /(node_modules|bower_components)/,
      use: {
        loader: 'babel-loader'
      }
    }
  ]
}

2、插件
A、babel-plugin-transform-runtime
babel-polyfill可以控制你自己写的文件,但是不能很好的处理第三方library,因为polyfill会污染原来的全局环境,容易发生冲突,这时候babel-runtime闪电登场。
babel-runtime是一个提供了regenerator、core-js和helpers的运行时库。
babel-plugin-transform-runtime插件依赖babel-runtime,babel-runtime是真正提供runtime环境的包,也就是说transform-runtime插件是把js代码中使用到的新原生对象和静态方法转换成对runtime实现包的引用。
a.1、利弊
可以用babel-runtime/core-js导出的对象和方法替代ES6引入的新原生对象和静态方法,避免全局污染;
可以用babel-runtime/regenerator导出的函数取代generators或async函数;
可以把多余代码提取到babel-runtime/helps中,减少体积。
由于runtime不会污染全局空间,所以实例方法是无法工作的,这就需要polyfill啦。

a.2、安装

# babel-plugin-transform-runtime用于开发环境
$ npm install --save-dev babel-plugin-transform-runtime

# babel-runtime用于生产环境
$ npm install --save babel-runtime

a.3、配置.babelrc文件

{
  "plugins": [
    ["transform-runtime", {
      "helpers": false,
      "polyfill": false,
      "regenerator": true,
      "moduleName": "babel-runtime"
    }]
  ]
}

a.4、使用

// ES6代码
var sym = Symbol();
// 通过transform-runtime转换后的ES5+runtime代码
var _symbol = require("babel-runtime/core-js/symbol");
var sym = (0, _symbol.default)();

五、babel-core,新语法转码
1、安装

$ npm install --save-dev babel-core 

2、使用

var babel = require("babel-core");

A、如果是字符串形式的JavaScript代码,可以使用transform编译。
babel.transform("code();", options);  // { code, map, ast }

B、如果是文件,异步编译使用transformFile。
babel.transformFile("filename.js", options, function(err, result) {
  result; // { code, map, ast }
});
C、如果是文件,同步编译使用transformFileSync。
babel.transformFileSync("filename.js", options);  // { code, map, ast }

D、要是已经有一个babel AST(抽象语法树)了就可以直接从AST进行转换。
babel.transformFromAst(ast, code, options); // { code, map, ast }

六、babel-polyfill,新Api转码
babel默认只转换新的JavaScript句法,而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。babel-polyfill正好可以转码新的API,polyfill和runtime都是对core-js和regenerator的再封装,方便使用。

插播一段,一直好奇polyfill是个啥东西,简单查了下,代码填充,也可译作兼容性补丁,类似软垫片。

1、安装

$ npm install --save-dev babel-polyfill

2、使用

//方案A,在your.js中引入
import 'babel-polyfill';

//方案B,在node.js中引入
require('babel-polyfill');

//方案C,设置webpack.config.js
module.exports = {
  entry: ["babel-polyfill", "./app/js"]
};

七、babel-cli,命令行转码
1、安装

$ npm install --save-dev babel-cli

2、命令行

# 转码结果输出到标准输出
$ babel example.js

# 转码结果写入一个文件
# --out-file 或 -o 参数指定输出文件
$ babel example.js --out-file compiled.js
# 或者
$ babel example.js -o compiled.js

# 整个目录转码
# --out-dir 或 -d 参数指定输出目录
$ babel src --out-dir lib
# 或者
$ babel src -d lib

# -s 参数生成source map文件
$ babel src -d lib -s

3、命令行优化
可以像上面一样直接输入命令完成转码,也可以修改package.json文件,然后执行npm run build。

"scripts": {
  "build": "babel src -d lib"
}

八、babel-register,require实时转码
通过绑定node.js的require来自动转译require引用的js代码文件。
babel-register模块改写require命令,为它加上一个钩子。此后,每当使用require加载.js、.jsx、.es和.es6后缀名的文件,就会先用babel进行转码。
1、安装

$ npm install --save-dev babel-register

2、使用

//必须先加载babel-register
require("babel-register");
require("./index.js");

3、利弊
这种方式不需要手动对index.js转码。
babel-register只会对require命令加载的文件转码,而不会对当前文件转码。另外,由于它是实时转码,所以只适合在开发环境使用。

九、sublime插件转码es6

1、安装插件
在sublime中,安装babel插件。
2、全局安装babel-cli包

cnpm install -g babel-cli

3、配置sublime中的babel插件

preferences -> Package Settings -> Babel -> Settings-Default,打开文件,按照下面的参数配置。
{
  "debug": false,
  "use_local_babel": true,
  "node_modules": {
    "windows": "C:/Users/Administrator/AppData/Roaming/npm/node_modules/babel-cli/node_modules",
    "linux": "/usr/lib/node_modules",
    "osx": "/usr/local/lib/node_modules"
  },
  "options": {}
}

4、配置.babelrc文件
在当前目录配置好.babelrc文件,定义转码规则,在当前目录放置好依赖包。

{
  "presets": ["es2015"],
  "plugins": []
}

5、执行转换
写一个es6.js文件,按下快捷键Ctrl+Shift+P,输入babel,选择babel transform执行,会自动生成一个匿名文件。很诡异的是,这个文件自动保存了,但不是在当前目录,也不是在sublime的包目录里,具体在哪,我也不清楚,我只知道这不是我想要的结果。我希望能够在保存es6.js文件时,自动生成期望目录的es5.js文件,而且名称一致,文件实际存在,不是无名文件。后面找到优化方案,再回来补充。

tools -> Babel -> Babel Transform,也可以执行转换。

十、在线转码
babel提供一个repl在线编译器,可以在线将ES6代码转为ES5代码。转换后的代码,可以直接作为ES5代码插入网页运行。

十一、总结
看了上面的介绍,你会用babel了吗?如果还有点迷惑,搞不清东南西北,看这里就对啦。
1、声明转换规则
babel的配置文件.babelrc列举了一些要用到的东西。比如babel要用env,就把env写进去,声明要处理哪些语法。
2、进行转换操作
幕后高人则是babel-core,babel-polyfill或者babel-cli,他们负责把源文件转换成目标文件。
安装了babel-core和babel-polyfill,并在你的源文件中引用,页面加载的时候,就会自动实现转换。或者安装babel-cli,在命令行输入命令,手动转换。

babel那些事儿的更多相关文章

  1. webpack 教程 那些事儿04-webpack项目实战分析

    这节主要讲解真正项目用用到的 webpack配置问题,项目实战篇 就像我们不会完全做一个项目,不用别人的轮子一样.这个配置我们借用 vue-cli 搭建的配置来研究,因为它已经足够优秀. 有了前面的基 ...

  2. postcss那些事儿

    一.sass和postcsssass.less.stylus,三者是css预处理器,使用预编码来处理css,然后编译成线上需要的css.postcss是处理你写好的css,让你的css更健康,对浏览器 ...

  3. 使用Babel和ES7创建JavaScript模块

    [编者按]本文主要介绍通过 ES7 与 Babel 建立 JavaScript 模块.文章系国内 ITOM 管理平台 OneAPM 工程师编译呈现,以下为正文. 去年,新版的JavaScript发布了 ...

  4. Babel 配置用法解析

    Babel 配置用法解析 刚复工的时候我司业务太多了,我已不记得我们连续作战了多少天,最近算是有时间可以学习学习我的babel大宝贝了,上周末看了下babel的一些核心模块以及babel的一些配置,今 ...

  5. 说说Makefile那些事儿

    说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...

  6. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  7. babel presets stage-x

    在一些新框架的代码中,常基于es6/7标准来书写代码.鉴于这些标准被没有被浏览器广泛支持,我们一般使用babel来将使用e6/7标准书写的代码降级编译(或者说转译)为浏览器可解析的es4/5代码. 以 ...

  8. setTimeout那些事儿

    一.setTimeout那些事儿之单线程 一直以来,大家都在说Javascript是单线程,浏览器无论在什么时候,都且只有一个线程在运行JavaScript程序. 但是,不知道大家有疑问没——就是我们 ...

  9. ES6转换器之Babel

    ES6部分功能没有支持,所以想学习ES6,得先有个转换器,就是将ES6的代码转换为ES5. 我这里用的是Gulp + Bable的形式来将ES6转换为ES5的. 前提: (1).Gulp和Bable都 ...

随机推荐

  1. Python基础之封装

    一.什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其 含义是其他程序无法调用. 要了解封装,离不开“私有化”,就是将类或者 ...

  2. Two Sum【LeetCode】

    Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...

  3. .Net(C#)用正则表达式清除HTML标签(包括script和style),保留纯本文(UEdit中编写的内容上传到数据库)

    去官网下载,本Demo用的MVC模式 下载地址:http://ueditor.baidu.com/website/download.html 加入文件夹中的结构: 引入了函数公式的图标: @{ Vie ...

  4. 将Elasticsearch的快照备份到HDFS

    1.安装Elasticsearch插件repository-hdfs 下载地址:https://artifacts.elastic.co/downloads/elasticsearch-plugins ...

  5. [转] Meida视频加密二-Blob对象

    2. blob 1 <video src="blob:http://www.bilibili.com/d0823f0f-2b2a-4fd6-a93a-e4c82173c107" ...

  6. Appearance-and-Relation Networks for Video Classification论文笔记 (ARTnet)

    ARTnet: caffe实现:代码 1 Motivation:How to model appearance and relation (motion) 主要工作是在3D卷积的基础上,提升了acti ...

  7. Tensorflow name_scope

    在 Tensorflow 当中有两种途径生成变量 variable, 一种是 tf.get_variable(), 另一种是 tf.Variable(). 使用tf.get_variable()定义的 ...

  8. weex用阿里矢量图

    首先这段代码来自 zwwill在github上的 weex网易严选项目 他是在utils下封装了一个方法 let utilFunc = { initIconFont () { let domModul ...

  9. [转]Oh My Zsh,安装,主题配置

    https://swp-song.com/2017/08/20/Tools/OhMyZsh%E5%AE%89%E8%A3%85%E5%92%8C%E4%B8%BB%E9%A2%98%E9%85%8D% ...

  10. Zabbix监控Low level discovery实时监控网站URL状态

    今天我们来聊一聊Low level discovery这个功能,我们为什么要用到loe level discovery这个功能呢? 很多时候,在使用zabbix监控一些东西,需要对类似于Itens进行 ...