BabelBabel是一个JavaScript编译器,可以将ES6+语法编译成浏览器支持的ES5语法。要想学好babel,首先要了解相关概念,但是如果一开始就扣掉这些细节,很可能babel的一些复杂模糊的概念会撞到你的资料上。因此,让我们从最简单的开始,然后再深入。最简单的例子接下来我们尝试按照官方文档做一个最简单的例子安装babel-clinpminstall--save-devbabel-cli添加babel编译命令"build":"babelsrc-dlib"添加.babelrc配置文件{"presets":[],"plugins":[]}添加JS文件///src/main.jsconstfetch=args=>args;console.log(Promise);执行npmrunbuild,我们发现编译后的文件没有任何变化,只是原样输出///lib/main.jsconstfetch=args=>args;控制台日志(承诺);为什么?这是因为.babelrc文件中没有进行任何配置。我们一共使用了三个新特性,分别是常量声明const、箭头函数=>和新的全局变量Promise。接下来我们尝试将它们编译成ES5代码。如上图所示,我们的目的可以借助插件来实现。接下来我们单独实现:const原文链接文档中写到:babel-plugin-check-es2015-constants这个插件只是为了验证const变量的规则,比如不可重复声明,不可变等特性。编译成ES5代码需要借助babel-plugin-transform-es2015-block-scoping。我们将要编译的代码设置为:constfetch=args=>args;取=55;//故意错误console.log(Promise);安装上面需要的两个插件,重写.babelrc配置:{"presets":[],"plugins":["check-es2015-constants","transform-es2015-block-scoping"]}编译过程报错验证check-es2015-constants是否生效我们修改需要编译的代码:constfetch=args=>args;控制台日志(承诺);再次编译成功varfetch=args=>args;控制台日志(承诺);到这里我们已经成功地使用插件来ES5izeconst语法和翻译(Syntaxandtransform)。你快乐吗?接下来我们处理箭头函数=>。箭头函数也安装相应的插件:npminstall--save-devbabel-plugin-transform-es2015-arrow-functions这里继续使用上面需要编译的源码:varfetch=args=>args;console。log(Promise);重写.babelrc配置文件:{"presets":[],"plugins":["check-es2015-constants","transform-es2015-block-scoping","transform-es2015-arrow-functions"]}编译结果:varfetch=function(args){returnargs;};控制台日志(承诺);编译成功,难以置信,我们做到了!!!,真的很简单吗?不要沾沾自喜???还有一个Promise没有解决。没有任何配置选项,babel-preset-env的行为与babel-preset-latest(或babel-preset-es2015、babel-preset-es2016和babel-preset-es2017一起)完全相同。无需做任何配置选项,与babel-preset-latest一致,或者babel-preset-es2015、babel-preset-es2016、babel-preset-es20174预设的总和。是不是感觉棒棒哒!让我们试试下面的例子。为了防止任何代码污染,我最初卸载了所有npm包:{"name":"babelrc","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo\"Error:notestspecified\"&&exit1","build":"babelsrc-dlib"},"author":"","license":"ISC","devDependencies":{}}我安装的时候发现@babel/preset-env还是bate版本的,使用起来还是有些问题,所以还是决定用老版本。(1)安装babel-preset-env上图是babel-preset-env的一些依赖,主要是一些helpers和plugins。为了验证babel-preset-env是否符合要求,我添加了几行包含ES6的代码:constfetch=args=>args;console.log(Promise);//添加一些代码classG{}let[a,b,c]=[1,2,3];(async()=>{awaitconsole.log(1)})();(2)configuration.babelrc{"presets":["env"],"plugins":[]}(3)编译结果"usestrict";函数_asyncToGenerator(fn){返回函数(){vargen=fn.apply(this,arguments);returnnewPromise(function(resolve,reject){functionstep(key,arg){try{varinfo=gen[key](arg);varvalue=info.value;}catch(error){拒绝(错误);return;}if(info.done){resolve(value);}else{returnPromise.resolve(value).then(function(value){step("next",value);},function(err){步骤("throw",err);});}}returnstep("next");});};}function_classCallCheck(instance,Constructor){if(!(instanceofConstructor)){thrownewTypeError("不能将类作为函数调用");}}varfetch=functionfetch(args){returnargs;};console.log(Promise);//添加一些代码varG=functi下面是一个例子:源代码classG{}.babelrc配置{"presets":["env"],"plugins":[]}编译代码"usestrict";function_classCallCheck(instance,Constructor){if(!(instanceofConstructor)){thrownewTypeError("不能将类作为函数调用");}}varG=functionG(){_classCallCheck(this,G);};//_classCallCheck是一个内部生成的帮助函数为了优化编译体积,babel团队推出了babel-plugin-transform-runtime+babel-运行时来解决这个问题。先看直观感受:源码classG{}.babelrc配置{"presets":["env"],"plugins":["transform-runtime"]}编译代码:"usestrict";var_classCallCheck2=require("babel-runtime/helpers/classCallCheck");var_classCallCheck3=_interopRequireDefault(_classCallCheck2);function_interopRequireDefault(obj){返回obj&&obj.__esModule?对象:{默认值:对象};}varG=functionG(){(0,_classCallCheck3.default)(this,G);};对比可以看出,方案二直接从babel-runtime引入了babel-runtime/helpers/classCallCheck,避免了自定义,从而减少了代码量。除了这个优势之外,babel-runtime主要有三个部分:core.js+helpers+regenerator当然,除了以上方法,引入polyfills和按需转换也可以带来更多的体量优化。减少不必要的浏览器的兼容性,以减少polyfills和transforms的引入:{"presets":[["env",{"targets":{//%指的是浏览器列表中用户的全球覆盖率"browsers":[">0.25%","notie11","notop_miniall"]}}]]}答案(1)可能你发现我没有安装babel-cli,为什么可以使用babel命令?因为我全局安装了babel。(2)更改了browserslistrc配置后,babel编译出来的代码没有变化。或者browserslistrc具体有什么表现影响babel编译?还不知道,正在研究,稍后更新。参考[1]browserslist[2]browserslist-example[3]browserslist-queries因为我的表达能力实在是太差了,表达不够清楚还望大家见谅。
