【转】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-0 $ npm install --save-dev babel-preset-stage-1 $ npm install --save-dev babel-preset-stage-2 $ npm install --save-dev babel-preset-stage-3
以上每种预设都依赖于紧随的后期阶段预设。例如,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,js,那些,runtime,事儿 来源: https://www.cnblogs.com/worldleader131/p/babel-sth.html