前一篇文章,我们简单描述了webpack的编译执行原理,要实现非SSR下的VUE持久化路由动态加载,需要解决两个问题:
1,module的key必须是固定值,不能随文件多少而变化,也就是持久化
2,路由对应的module,由开发编译改为运行加载,即:
从数据库中获取数据,然后运行时组装成webpack编译后的样子。
webpack编译后的chuck和module是连续数字,0是默认自动加载。如果要持久化,就必须把数字换成唯一能标识的值。
方案如下:
一:js文件名称直接用官方提供的,code split方案即可,然后会编译成块名称,比如
const IndexPage = r => require.ensure([], () => r(require('./src/vue/frame/Index.vue')), 'Index')
编译后,是Index.js
二:module名称持久化使用NamedModulesPlugin(相对路径的缺陷蛮多,姑且不论)
然后这样就ok了么?No!!!,由于笔者使用的是webpack1.x版本,编译后运行会发生异常。
需要做如下处理,目前最新版本的webpack已经不存在该问题
如图,这里有一个chunk.id类型的判断。
既然实现了持久化,那么剩下的问题就是在什么时机去获取数据库,运行加载。
路由配置文件会有一个独立的moduleid,如下图红色标记的部分
由于routerHandle里涉及比较多的业务信息,就不贴了。既然有了切入点,在routerHandle只需要干两个事情
1,ajax去获取数据,当然得同步获取
2,根据数据,组装成如下样式即可:
var IndexPage = function IndexPage(r) {
return __webpack_require__.e/* nsure */('xxx', function () {\n return r(__webpack_require__(\"yyy\"));\n });\n};
为了方便开发使用,我们对路由维护做了单独的UI,功能如下:
1,支持上传路由配置js文件,直接解析存储数据库
2,上传编译后的js文件,由运行平台自动加载
3,加入版本控制
等等
结语:
由于笔者是从webpack1的基础上去实现,蛮多波折。
还是希望官方能正式提供一种完善的持久化方案。目前虽然能实现,但缺点很多就不一一列举了。
就项目实际情况看,这是一种刚需。比如多部门合作项目,整体编译不现实,特别是涉及生产环境文件更新,改了什么更新什么,而不是整体替换。
开发时比重过多,运行时比重较小,灵活性不好。