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都 ...
随机推荐
- JPA整合Spring案例
目录 Spring-SpringMVC-JPA整合案例 三种整合方式 Spring整合JPA步骤 解决JPA懒加载问题 Spring-SpringMVC-JPA整合案例 author :SimpleW ...
- 【linux】复制文件夹内容到另一个文件夹
我一直觉得cp是个非常简单的指令.结果居然遇到坑了.记录一下. 文件夹1:test1/ 文件夹2:test2/ 目标:将test1/中的所有文件和目录拷贝到test2/中 正确指令: cp -rf t ...
- tp3.2 事务
public function exchangeTransfer($user_id, $type, $money, $config, $other_id = 0) { $r['code'] = ERR ...
- Redis扩展
Redis扩展下载地址:https://windows.php.net/downloads/pecl/releases/redis/ PHP怎么安装redis扩展 http://www.php.cn/ ...
- HTML添加图像和超链接
添加图像 <img src="图像的文件地址" alt="加载失败" height="350" width="350&quo ...
- vsftpd中的local_umask和anon_umask
umask是在linux中常见的一个东西,它其实是一个掩码.当然,也有umask这样一个命令,它是对用户建立的文件的默认属性的定义.该 定义为: 假设umask为022,则对于一个文件夹的话,它的默认 ...
- vue指令问题
挂载点:最外层标签就是vue实例的挂载点,即id或者类对应的 dom节点 模板:指挂载点内部的内容,在实例里使用template标签来构 建 h1标签放在body里面不使用 “template”是一样 ...
- 论文阅读笔记二十三:Learning to Segment Instances in Videos with Spatial Propagation Network(CVPR2017)
论文源址:https://arxiv.org/abs/1709.04609 摘要 该文提出了基于深度学习的实例分割框架,主要分为三步,(1)训练一个基于ResNet-101的通用模型,用于分割图像中的 ...
- Java中堆内存和栈内存的区别
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空 ...
- .net remoting(1)简单例子
1.例子(程序间的通讯) class Program { static void Main(string[] args) { HttpChannel _channel = ); ChannelServ ...