近来又遇到了很恶心的事儿,那就是想要升级babel为6的时候,遇到了新老AMD模块并存的问题。
是的,又遇到了,尽管在babel7都WIP了,升级个6还是恶心的够呛,扫了一圈之后发现,圈里貌似还是没人去解决这个问题……
先列出引到的链接:
我开发的小插件: babel-plugin-transform-es2015-modules-existed-amd
问题症结
主要是新老模块并存导致的。
简而言之,babel6的插件babel-plugin-transform-es2015-modules-amd
在处理的时候,由于面临着这样的使用状况(示例代码):
|
|
可以看到export let了tested,default里面也有tested,那么应该是哪个?
所以babel6定义为:
|
|
多了一个default
,所以babel6翻译过的import 'a'
都变成了require('a').default
。然而它并不会处理旧的那些AMD的模块,而如果你“不幸”的在旧的模块中去require了新的es6的模块,就挂了……
关键点在于,babel6的做法没什么问题,只是不兼容旧的而已,而插件babel-plugin-transform-es2015-modules-simple-amd
的解决方案是将babel6的AMD转换输出改成babel5的方式,去掉default
,但是如果你用了export let,那就只能sorry了,搞不了。
扫了一些文章基本结论都是:ES6 module to AMD的转码逻辑变更并且暂时没有什么好的办法解决这个问题。
还有!
babel-plugin-transform-es2015-modules-amd
在处理旧的AMD
和UMD
,都会在外面给包一层define
,醉了么?
硬着头皮处理
或者可以解决的方案:不修改babel6,而是针对旧AMD模块,然后采用插件的方式处理,将它的输出也加个default
,require的部分也是一样。
先只处理简单的状况!!
下面都是使用了 preset es2015 和 babel-plugin-transform-es2015-modules-amd
,所以代码会先被转换一次。
为啥要用?因为不想去处理 es2015模块啊,万一人家支持了,我们只要撤掉这个插件就好了。
列一下要面对的问题:
- 旧模块的定义
- 定位模块主体
- require的处理
- exports的处理
定义
限制为使用define
来定义的模块,形如:
|
|
模块主体部分
define
一共有四种形式(变参):
|
|
无论是用哪种,主体都是factory
,最后一个参数。
不过其实要处理的是babel-plugin-transform-es2015-modules-amd
搞进来的define
部分。
|
|
require的处理
我是个较懒的人,所以选择的方式是这样的。
找到对应的点,然后使用自带的 _ref.types
即 babel-types
的方法callExpression
来替换原节点……
在 visitor.Program.exit 中 path.traverse(amdVisitor, this);
来遍历
然后就直接处理了,区分了几个使用的场景,没效率,但是架不住简单。
因为是包了一层调用,所以还得加个函数进去,这个简单,ast node直接用babel-template
搞就行了。
|
|
没有搞 Gloabl require,形如 require(['main']);
,先手改吧。
至此的效果:
|
|
最后,要说的是:
如果遇到了这样的问题,只能改代码了,因为根据babel6的设计,这样本来就是不行的:
|
|