如何动态加载并执行远程vue组件

By | 2017年10月22日

为何需要远程加载vue组件?

正常使用vue开发单页web app的时候不会遇到这种需求。不过当开发的产品作为一个服务平台,并允许第三方开发者在平台上发布自己的应用;或者需要在应用中加入插件机制方便扩展,但是又不想使用[iframe嵌入]这种low到没朋友的方式实现的话,就需要考虑是不是可以将远程模块xiu的一下抓过来执行了~

如何远程加载?

使用vue开发的项目大多会用webpack配合进行编译,而webpack是在编译阶段对vue或者js文件进行静态依赖分析,不管三七二十一将这些文件啪啪啪~交给各种loader处理,然后打包生成一个让人一眼看过去就会懵比的js文件给浏览器运行。vue-loader这种编译完就无所事事的家伙,自然是不能指望在运行时还让他继续工作的。所以如果想要远程直接加载vue文件并运行的同学可以洗洗睡了。

那么将webpack打包之后的js远程取过来过来试试呢?事实证明webpack还是很给力,打包出来的js文件远程加载到平台环境中完全没有问题。不过要注意的是这个时候不能采用分片打包的方式,否则加载的入口文件会找不到依赖的 ^0^

那么下一个问题来了,如何让这个远道而来的js一家在我们平台中优雅的玩耍呢?此处有几种方式可以选择,不过目前感觉不错的一种方式是利用vue的动态组件:

<component :is="remoteFriend"></component>

根据动态组件的使用方法,似乎还要给这个可怜的模块起一个名字先:Vue.component(‘xxx’, xxx)。可是作为日理万机的平台,哪有时间给这么多流浪者天天想名字啊!而且万一起的名字不合适大家还怎么开心的玩耍了~
回想一下发布的时候我们交给平台的是一个js文件(其实只有一个远程的url地址),那么组件的名称是否可以让这个js事先自己取好并自己注册上去呢,比如加一个entry.js:

const name = 'laowang'
Vue.component(name, require('./laowang'));
return name;

现在webpack打包的对象变成了entry.js,这个js被平台远程获取并加载的时候就自然而然的注册了vue组件,并将自己起好的名字返回出来给动态组件使用!

但是似乎还有一个问题:

路由怎么处理?

要说明的是此方法在vue1.0的前提下实现

现在我们使用了动态组件加载远程模块,但是如果远程模块中包含子路由**&%¥#@,这又是一个悲伤的故事了!

如何将平台的路由和远程模块的路由无的集成到一起呢?目前看来只有从路由本身的机制着手了,直观的思考,只要看vue-router动态加子路由的接口比如addSubRouter就可以完工了。可以现实不比理想,翻遍接口文档居然都木有此接口,木有!

万幸在源码中发现了一个暴露的私有方法(有点诡异啊):_addRoute,经过一系列的构造参数,最终还是可以将子路由妥妥的加到平台的路由机制里。不幸的是现在vue-router升到2了~~ 还木有来得及研究。

还有?

大概的过程基本如上,还有要注意的话就是远程模块中的ajax请求需要通过绝对路径访问,而且服务器要做跨域设置。基于此限制,加载远程js的时候就可以直接用ajax,都允许跨域了么~~

最后,将以上方法封装了两下,一个是丢在远程的自动打包发布功能,一个是平台中的加载功能。
vue远程加载工具,详情可见README。

发表评论

电子邮件地址不会被公开。 必填项已用*标注