webpack之babel插件困惑解疑

此前,我在react项目中使用了es6语法,例如:class关键字。然而nodejs本身是不支持es6语法的,更重要的是落后的浏览器也不支持es6语法,为了能够让它们理解es6语法,我们使用了babel插件来将es6转义为es5语法。

这里重要的是语法两个字,之前用到的babel-core模块以及babel-preset-es2015插件仅仅完成了es6语法转es5语法,而es6规范新增了很多类和API并没有被添加进来,例如: Promise、Set、Map 等新增对象,Object.assign、Object.entries等静态方法。

回想此前用redux的时候,用到了Object.assign这个es6的对象静态方法貌似也能正常work,这又是为何?这是因为我的浏览器chrome版本较高,能够支持es6的的API,那么旧版本的浏览器又怎么办呢?

为了保证新老浏览器都可以正常使用es6的新api,因此最好在编译代码的时候进行polyfill(也就是替换),简单的说:实现一套es6新api的es5版本实现,然后编译的时候将代码中用到es6 api的代码都替换成对应的es5实现,这样无论什么样的浏览器都可以正常运行了。

安装插件

为了达成这个目的,社区又有2个实现流派:babel-polyfill和babel-runtime+babel-plugin-transform-runtime,至于两者到底有何差异可以阅读:点我,看完后就明白究竟了。

我个人当然倾向于不污染全局的babel-runtime+babel-plugin-transform-runtime方案了,安装方法如下:

安装完成后,需要修改一下webpack.config.js,让babel-loader通过babel-plugin-transform-runtime插件帮我们将代码中的es6 api调用进行自动替换,也就引入babel-runtime作为运行时环境(也就是es5语法实现的es6 api)。

修改后的配置如上,增加了transform-runtime插件来自动的生效babel-runtime。

测试效果

那么怎么确认一下上述babel插件是否生效呢?我是通过查看webpack编译后的代码判断的。

首先,我为代码添加了一行console.log(Object.assign),在我配置transform-runtime插件之前,编译出的bundle.js中这行代码原样摆在那里,也就是使用浏览器的native api。在配置插件之后,相关的代码变成了这样:console.log(_assign2.default),是一种兼容方案。

同样的,我添加代码let myset = new Set(),配置插件之后也变成了:var mySet = new _set2.default();

另外,通过阅读上面的babel插件原理可知,babel-runtime方案无法支持对象方法(基于原型链注入的方法)而babel-polyfill可以做到,这是当前一个无法避免的2选1问题。

额外学习

上面看样是work了,可以在github上看到完整配置

从此之后,我就可以多用用Es6的新API来节省我的工作量了,有兴趣可以再看看阮一峰关于babel插件的介绍,以及这一篇博客

发表评论

电子邮件地址不会被公开。