简单来说:写一个大项目,然后有很多小项目,大项目可以动态引用小项目(页面或组件)而无须重新打包发布 举个例子:大项目就好比是 vscode,小项目就是 vscode 的一个个插件,可以随意下载使用插件而不用每次都更新 vscode 版本,并且插件可以单独升级
1
SilentDepth 2019-07-10 10:16:51 +08:00
这不就是各种 Vue 组件库的效果?
活用 Vue.use()、Vue.component()、<component :is="?"> |
2
duanzs OP @SilentDepth 请注意审题哈 项目是分开的,而且小项目升级部署都不用发布大项目
|
3
SilentDepth 2019-07-10 10:26:35 +08:00
是啊,element-ui 和业务应用的项目也是分开的啊,如果 element-ui 的引用方式是 CDN ( HTTP 链接),人家更新也不需要你重新发布业务应用啊
|
4
mozhizhu 2019-07-10 10:28:59 +08:00
其实跟 webpack 的热更新是差不多的想法;
比如服务器渲染的方法,例如 nuxt ; |
5
duanzs OP @SilentDepth 他就是个样式库,没可比性吧
|
6
SilentDepth 2019-07-10 10:46:16 +08:00
@duanzs #5 那好,Vue Router,这个不是样式库吧,要方法有方法,要组件有组件,你可以看看它是怎么做的。
|
7
SilentDepth 2019-07-10 10:50:01 +08:00
@duanzs #5 不要先入为主觉得 element-ui 就是个组件库所以没有参考性,其实大家的本质都是一样的,无非是动态注册的东西不一样而已。
|
8
duanzs OP @SilentDepth 我觉的咱俩理解不一致,我的需求是能动态引入而无需重新打包发布的
|
9
wly19960911 2019-07-10 11:20:11 +08:00
首先理解路由懒加载原理,你就知道什么解决方案了。使用 requirejs 应该可以做到,但是现在的编译环境应该不行,因为项目的依赖已经完全被处理过了。
|
10
sohu022 2019-07-10 11:23:17 +08:00
目前我们这边也在基于 Vue 开发一个类似的项目管理平台, 主应用包含核心和通用的功能, 同时提供给用户开发插件的能力, 系统预埋一些扩展点, 用户可以使用插件来扩展系统的支持自定义扩展的块、 菜单、路由 等功能,
主应用与所有的插件都是单独编译的, 插件编译好跟随插件的后台服务一起打包成一个插件的 Java jar 包, 上传到系统中, 在管理后台可以针对特定的项目启用该插件, 应该跟楼主说的这种比较类似了 |
11
sohu022 2019-07-10 11:24:20 +08:00
每一个插件也可以单独启用某一个版本的该插件
|
12
duanzs OP @wly19960911 应该不满足我需求,因为我要求主项目不需要每次都重新构建发布
|
13
SilentDepth 2019-07-10 11:31:49 +08:00
@duanzs #8 我说的就是「动态引入而无需重新打包发布」啊。
Vue 动态添加应用能力就是靠 Vue.use( )(以及相关的 Vue.mixin( )、Vue.component( )、Vue.directive( ) 等),接受的参数就是一个 Plain JS Object,那么你的问题就变成「如何在不重新编译引用者的情况下获得这个 Plain JS Object 」。最简单的,如楼上所说用 RequireJS,或者自己实现一个简单的异步模块加载器(动态添加 <script>,用全局函数得到模块内容),只要目标模块地址可以在运行时确定,模块引用者(主业务应用)就不需要重新编译和发布,目标模块暴露一个 install 方法传给 Vue.use( ) 去调用,就完事了。 我举 element-ui 和 vue-router 的例子,是因为它们也是这么做的。 |
15
duanzs OP @SilentDepth 我觉得还是有区别,你描述的引入 element-ui 和 vue-router,是因为你提前知道要引入这俩模块,但是你想一下 vscode,开发 vscode 的时候他们知道有多少插件吗?
|
16
SilentDepth 2019-07-10 11:40:26 +08:00
@duanzs #15 这个不重要呀,你需要的只是一个包的地址而已。我提 element-ui 和 vue-router 是为了引入具体场景来强调「异步加载」这个事儿,是不是 element-ui 不是问题的重点。
|
17
Rorysky 2019-07-10 11:40:30 +08:00 via iPhone
后端 动态链接库
|
18
SilentDepth 2019-07-10 11:41:30 +08:00
unpkg.com 上那么多包,你随便选一个得到地址,架设你刚好选的就是 element-ui,接下来不就和正常加载 element-ui 一个过程了?
|
19
learnshare 2019-07-10 11:42:20 +08:00
element 可不是个样式库,兄弟
你需要解决的是按需加载、注册和执行 |
20
Rorysky 2019-07-10 11:45:14 +08:00 via iPhone
前端比后端设计模式落后一个世纪,这个问题上个世纪都解决的很好
|
21
doublleft 2019-07-10 11:50:55 +08:00
@duanzs 我也遇到并设计过这样的系统,并且走了很深(将近一年),分享下历程 希望对你有帮助吧。
可插拔系统要求的是各个小组件组成的大系统。小组件设计要支持单独新增、发布、独立测试,大系统不用一起打包发布。我的业务场景是实现一个几百张的表单、表格、图形的查询页面。很多组件是可以重用的。 1. 最开始是用 iframe 实现,封装成大系统+若干小系统,每个系统都是独立的 react 工程,关键点是要解决的是组件之间通讯问题。后来因为维护太多小系统,又用 webpack 封装了统一的打包发布脚手架和 CI/CD,这是第一版。 2. 第二版我动手设计了一个 runtime 的渲染项目,把之前的小工程改为 npm 包 一个小组件。根据访问 router 向服务器拉取组件配置,这个配置描述了页面有哪些组件、他们的位置 类别 事件 关联组件等,比如 input 放在哪里。这些颗粒组件也是事先写好、独立测试发布、低耦合、不含业务的。不过最终还是有拆解不了的,当时解决办法就是单独放在业务工程,打包好一起下发。 这样做看似优雅,其实还是有很多问题和优化空间,比如线上并行版本太多、很考验封装能力、框架升级要 rebuild 所有,要严格的设计状态控制等。 其实如果继续发展下次我想应该是一个类似“中台”表单设计器,我当时已经封装了不少基础组件( Input、Button、Select、Radio 等),定制了超级复杂的 Table (支持多表关联 下钻 子 Table 固定行列),又整合了 E-Chats 进去,又实现了全数据驱动,完全可以实现运营同学手动拖拽设计表单。 这套系统根据业务需求,最后支持全国几万家门店定制的数百个表单查询,不过后来因为不是重点项目,慢慢就被剥离出来了。 |
22
wly19960911 2019-07-10 12:06:27 +08:00 via Android
@Rorysky 前端的 script 标签不是动态链接库了?
他要的不是动态链接库,而是动态链接模块,在原有的运行模块中再次启动一个模块。 我只学过 Java,我不知道怎么在运行中的项目怎么插入一个 controller …至少可能实现也很麻烦。 |
23
Rorysky 2019-07-10 12:09:23 +08:00
@wly19960911 不扯别的,本质都是 对象 及 接口调用
|
24
loading 2019-07-10 12:13:00 +08:00 via Android
@SilentDepth 还敢用 cdn 不指明版本号?上次圣诞节下雪的事忘了?
|
25
wly19960911 2019-07-10 12:13:14 +08:00 via Android
@Rorysky 但是框架没有整合,现在要求框架拥有动态模块的能力。就跟楼上一样对框架进行了 hack 或者直接 script 使用框架的库(只有库),做到当然可以。
|
26
SilentDepth 2019-07-10 12:46:38 +08:00
@loading #24 我有建议不指明版本号吗?都说了 element-ui 和 vue-router 是针对「异步加载」的举例,咱能聊聊异步加载方面的事儿不?
而且,antd 跟版本号有啥关系?你怎么知道你锁定的不是下雪版本呢? |
27
lecion 2019-07-10 13:11:09 +08:00 via Android
听起来有点微前端的意思
|
28
duanzs OP @SilentDepth 所以这就是区别点,因为我需求是预先不知道有哪些子模块
|
30
duanzs OP @learnshare 对,所以我就是问怎么解决
|
33
SilentDepth 2019-07-10 14:30:17 +08:00
我不明白你为什么要纠结于「是否预先知晓模块信息」这一点。
所有模块都可以转换成一个 JS 文件。我们约定这个 JS 文件会以某种方式输出一个 Plain JS Object,并且包含一个 install 方法,这样就可以通过 Vue 插件机制 ( https://cn.vuejs.org/v2/guide/plugins.html) 动态注册到 Vue 应用中。接下来你只需要解决「获取这个 JS 文件」的问题即可。解决起来也不难,理论上任何异步加载 JS 资源的方案都可以。在整个这个过程中你的主业务应用不需要做任何变化(当然主业务应用本身要实现插件系统的底层支持)。 至于从哪里加载,当然会有一个后端服务提供模块清单(就好比 VS Code 的插件搜索),但这个事情是业务的事情,并且与主业务应用无关了(除非搜索功能本身是主业务应用提供的)。确定待加载模块列表(不论是自动生成的还是用户手动选择的),转换为各模块的 URL,依次加载对应的 JS 文件并调用其中的 install 方法(通过 Vue.use( )),一个「插」系统就实现了。 这里唯一需要额外实现的是「拔」,因为并没有一个 Vue.unuse( ),Vue 也不识别 uninstall 方法。但既然模块本身已经在本地了,手动调用 uninstall 方法并没有什么障碍,实现相应的卸载逻辑即可。 |
34
duanzs OP @SilentDepth 关于纠结 纠结于「是否预先知晓模块信息」这一点:我觉得是我连子模块信息都不知道更谈不上引用了。
关于整体回复:我觉得主项目使用 Vue.use( )之后不应该还得去把主项目打包发布吗? |
35
SilentDepth 2019-07-10 16:30:12 +08:00
@duanzs #34 你是不是误解了什么。
function loadExternalModule (url) { document.createElement('script') /* ... */ } 有了这样一个函数,只要能有一个 url,是不是就可以在运行时加载一个外部 JS 模块了呢?至于模块信息……你(的业务)总得设计一个机制来生成或获得模块信息啊,不然插件系统做出来要怎么用? function useExternalPlugin (plugin) { Vue.use(plugin) /* ... */ } 有了这样一个函数,只要能有一个插件对象(通过 loadExternalModule( ) 获得),是不是就可以在运行时注册一个外部 Vue 插件呢?完全不需要重新编译主项目。 |
36
sodatea 2019-07-10 16:36:15 +08:00
不知道你需要的是不是这种模式:
https://medium.com/@cramforce/designing-very-large-javascript-applications-6e013a3291a3 enhance instead of import |
37
duanzs OP @SilentDepth 感谢老哥指点,对这块确实基础薄弱
这里我再 引申 /直白 一下问题。 举一个例子,有一个子项目,比如说是用 vue 写的一个单页计算器 子项目肯定是以单独项目的方式去打包,再以某种方式发布到主项目中。子项目( webpack )打包出来可能会有 index.html、bundle.js 、css、大图片等。这种怎么去 use。 |
40
SilentDepth 2019-07-10 17:09:01 +08:00
@duanzs #37 这个要分情况了。
如果子项目本身就可以独立运作并发挥业务价值(有自己的业务环境、root 实例、入口页、整体布局等),只是在特定情况下需要「嵌入」到一个更大的应用中,但内外并没有太多交互,那么你可以考虑 <iframe>——这种情况,你只是希望两个应用显示在一个页面中。(这种情况讲道理不能算「插件」。) 而,如果你不想用 <iframe>,你可以考虑 Vue-in-Vue (我瞎编的术语)。子项目的也是一个完整的 Vue 应用,其实只是需要一个 mountpoint 而已,那么主项目应用留出这么一个元素让子项目去 mount 即可。此时子项目的 install 方法就是一句 new Vue(...).$mount(...)。 如果子项目是一个业务模块,需要依赖外部环境才能发挥业务价值,那么子项目的 index.html 应该只是为了方便独立开发调试而存在,真正 build 出来的应该是一个库(也就是 dev 和 build 是两套打包流程)。剩下的就跟 element-ui、vue-router 等没什么本质不同了。 |
41
SilentDepth 2019-07-10 17:15:58 +08:00
@sodatea #36 (文章真长!)我觉得他想要的是这种模式。
@duanzs #38 找到了一个翻译版: https://hijiangtao.github.io/2018/04/20/Designing-Very-Large-JavaScript-Applications/ |
42
hailun3202475 2019-07-18 10:29:06 +08:00
@duanzs 你好,我们公司最近也是要做一个和你一样需求的项目,请问你现在进展如何,我自己找了找部分文档应该是比较符合我们的需求
用微前端的方式搭建类单页应用: https://mp.weixin.qq.com/s/DpFXTrQ3_kBX4EB6or4Q8Q 对应的 demo 开源项目: https://gitee.com/newgateway/xdh-web (不太确定算不算,还没仔细看) |