babel那些事儿
从前,一提到新东西,我的反应就是兼容性好不好,如果不能满足产品经理的需求,就还是用保守的方式实现吧。毕竟前端开发是一件很灵活的事,怎么写都行,至于为何会用某种方法,一定是综合考虑兼容性,性能,用户体验,开发成本等因素后再说。兼容性和新事物有时就像鱼和熊掌不可兼得,必须权衡利弊,做一个决断。但是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那些事儿的更多相关文章
- webpack 教程 那些事儿04-webpack项目实战分析
这节主要讲解真正项目用用到的 webpack配置问题,项目实战篇 就像我们不会完全做一个项目,不用别人的轮子一样.这个配置我们借用 vue-cli 搭建的配置来研究,因为它已经足够优秀. 有了前面的基 ...
- postcss那些事儿
一.sass和postcsssass.less.stylus,三者是css预处理器,使用预编码来处理css,然后编译成线上需要的css.postcss是处理你写好的css,让你的css更健康,对浏览器 ...
- 使用Babel和ES7创建JavaScript模块
[编者按]本文主要介绍通过 ES7 与 Babel 建立 JavaScript 模块.文章系国内 ITOM 管理平台 OneAPM 工程师编译呈现,以下为正文. 去年,新版的JavaScript发布了 ...
- Babel 配置用法解析
Babel 配置用法解析 刚复工的时候我司业务太多了,我已不记得我们连续作战了多少天,最近算是有时间可以学习学习我的babel大宝贝了,上周末看了下babel的一些核心模块以及babel的一些配置,今 ...
- 说说Makefile那些事儿
说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...
- 总结iOS开发中的断点续传那些事儿
前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...
- babel presets stage-x
在一些新框架的代码中,常基于es6/7标准来书写代码.鉴于这些标准被没有被浏览器广泛支持,我们一般使用babel来将使用e6/7标准书写的代码降级编译(或者说转译)为浏览器可解析的es4/5代码. 以 ...
- setTimeout那些事儿
一.setTimeout那些事儿之单线程 一直以来,大家都在说Javascript是单线程,浏览器无论在什么时候,都且只有一个线程在运行JavaScript程序. 但是,不知道大家有疑问没——就是我们 ...
- ES6转换器之Babel
ES6部分功能没有支持,所以想学习ES6,得先有个转换器,就是将ES6的代码转换为ES5. 我这里用的是Gulp + Bable的形式来将ES6转换为ES5的. 前提: (1).Gulp和Bable都 ...
随机推荐
- Python基础之封装
一.什么是封装 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其 含义是其他程序无法调用. 要了解封装,离不开“私有化”,就是将类或者 ...
- Two Sum【LeetCode】
Given an array of integers, return indices of the two numbers such that they add up to a specific ta ...
- .Net(C#)用正则表达式清除HTML标签(包括script和style),保留纯本文(UEdit中编写的内容上传到数据库)
去官网下载,本Demo用的MVC模式 下载地址:http://ueditor.baidu.com/website/download.html 加入文件夹中的结构: 引入了函数公式的图标: @{ Vie ...
- 将Elasticsearch的快照备份到HDFS
1.安装Elasticsearch插件repository-hdfs 下载地址:https://artifacts.elastic.co/downloads/elasticsearch-plugins ...
- [转] Meida视频加密二-Blob对象
2. blob 1 <video src="blob:http://www.bilibili.com/d0823f0f-2b2a-4fd6-a93a-e4c82173c107" ...
- Appearance-and-Relation Networks for Video Classification论文笔记 (ARTnet)
ARTnet: caffe实现:代码 1 Motivation:How to model appearance and relation (motion) 主要工作是在3D卷积的基础上,提升了acti ...
- Tensorflow name_scope
在 Tensorflow 当中有两种途径生成变量 variable, 一种是 tf.get_variable(), 另一种是 tf.Variable(). 使用tf.get_variable()定义的 ...
- weex用阿里矢量图
首先这段代码来自 zwwill在github上的 weex网易严选项目 他是在utils下封装了一个方法 let utilFunc = { initIconFont () { let domModul ...
- [转]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% ...
- Zabbix监控Low level discovery实时监控网站URL状态
今天我们来聊一聊Low level discovery这个功能,我们为什么要用到loe level discovery这个功能呢? 很多时候,在使用zabbix监控一些东西,需要对类似于Itens进行 ...