qiankun
qiankun copied to clipboard
[Feature Request] qiankun 如何复用公共依赖
Background
如果主项目和子项目都用到了同一个版本的 vue/vuex/vue-router
等,主项目加载一遍之后,子项目又加载一遍,就很浪费。
要想复用公共依赖,前提条件是子项目必须配置externals
,这样依赖就不会打包进chunk-vendors.js
,才能复用已有的公共依赖。
按需引入公共依赖,有两个层面:
- 没有使用到的依赖不加载
- 大插件只加载需要的部分,例如
elementUI
组件库的按需加载、echarts/lodash
的按需加载。
Proposal
巨无霸应用的公共依赖和公共函数被太多的页面使用,导致升级和改动困难,使用微前端可以让各个子项目独立拥有自己的依赖,互不干扰。而我们想要复用公共依赖,这与微前端的理念是相悖的。
所以我的想法是:父项目提供公共依赖,子项目可以自由选择用或者不用。
这个也很好实现,父项目先加载好依赖,然后在注册子项目时,将vue/vuex/vue-router
等通过 props
传过去,子项目可以选择用或者不用。
这样做不太可行,原因有两个:
- 子项目独立运行时,
VueRouter/Vuex
这些依赖从哪里来?子项目是只部署一份的,既可以独立运行,也可以被qiankun
集成。 - 父项目只能传递它自己已经有的依赖,如何确定子项目需要哪些依赖?不满足按需引入的需求
要想实现按需引入依赖,配置webpack
的 externals
是必须的,而配置了这个之后,子项目独立运行时,这些依赖的来源有且仅有 index.html
中的外链 script
标签。
在这个前提下,能否做到,子项目和主项目的vue
版本一致的情况下,使用同一份服务器文件。即使无法共享,也是可以做http
缓存的。
那么 qiankun
能否做到,某个依赖加载了之后,不再加载,直接复用呢?比如说子项目A请求了服务器上的2.6版本vue
,切换到子项目B,B项目也用了这个vue
文件,能否不再次加载,直接复用呢?
其实是可以的,可以看到 qiankun
将子项目的外链 script
标签,内容请求到之后,会记录到一个全局变量中,下次再次使用,他会先从这个全局变量中取。这样就会实现内容的复用,只要保证两个链接的url
一致即可。
所以只要子项目配置了webpack
的 externals
,并在 index.html
中使用外链 script
引入这些公共依赖,只要这些公共依赖在同一台服务器上,便可以实现子项目的公共依赖的按需引入,一个项目使用了之后,另一个项目使用不再重复加载,可以直接复用这个文件。
Additional context
虽然 qiankun
不会重复请求相同 url
的公共依赖,但是这也仅比 http
缓存强了一丢丢。
有缺陷的地方在于:
- 主项目中的公共依赖没有记录到这个缓存中,也就不会被其他的项目复用
- 只是没有重复请求,还是需要重复执行一次。能否不执行,直接复用?
js
沙箱在子系统卸载时,会移除window
上新增的变量,而webpack
的externals
恰恰是将这些公共依赖挂载在window
上,能否看情况移除这些公共依赖? - 相同版本的依赖会复用,版本不同但是使用无差别,能否做到也复用?(版本不同
url
也就不同,就不会复用)
补充一点:如果子项目需要复用主项目的依赖,只需要给子项目 index.html
中公共依赖的 script
和 link
标签加上 ignore
属性(这是自定义的属性,非标准属性)。
有了这个属性,qiankun
便不会再去加载这个 js/css
,而子项目独立运行,这些 js/css
仍能被加载,如此,便实现了“子项目复用主项目的依赖”。
<link ignore rel="stylesheet" href="//cnd.com/antd.css">
<script ignore src="//cnd.com/antd.js"></script>
需要注意的是,主项目中的公共依赖需要暴露出来(挂载到 window
上),且需要和子项目版本保持一致。
补充一点:如果子项目需要复用主项目的依赖,只需要给子项目
index.html
中公共依赖的script
和link
标签加上ignore
属性(这是自定义的属性,非标准属性)。有了这个属性,
qiankun
便不会再去加载这个js/css
,而子项目独立运行,这些js/css
仍能被加载,如此,便实现了“子项目复用主项目的依赖”。<link ignore rel="stylesheet" href="//cnd.com/antd.css"> <script ignore src="//cnd.com/antd.js"></script>
需要注意的是,主项目中的公共依赖需要暴露出来(挂载到
window
上),且需要和子项目版本保持一致。
这是我目前提取的公共依赖,公共的都好说,就是自己的pk-view是自己封装的组件,但无法将其挂载在window上,vuecli的--target lib和--target wc好像无法实现,楼主方便解惑吗
是我目前提取的公共依赖,公共的都好说,就是自己的pk-view是自己封装的组件,但无法将其挂载在window上,vuecli的--target lib和--target wc好像无法实现,楼主方便解
pk-view 是只有一个组件吗,还是很多个组件。配一个环境变量,可以单独对他进行一次打包,入口文件就是这个组件,很多个组件就单独写一个 index.js
,导出这些组件,然后 --target lib 就可以了
是我目前提取的公共依赖,公共的都好说,就是自己的pk-view是自己封装的组件,但无法将其挂载在window上,vuecli的--target lib和--target wc好像无法实现,楼主方便解
pk-view 是只有一个组件吗,还是很多个组件。配一个环境变量,可以单独对他进行一次打包,入口文件就是这个组件,很多个组件就单独写一个
index.js
,导出这些组件,然后 --target lib 就可以了
组件库,我可能问的问题不对,不过还是谢谢啦
求一个复用公共依赖的demo
建议参考systemjs + webpack externals
请问楼主
- 上面说的props传递的方式,不可行的原因1没太理解,子应用为啥会有单独运行的场景呢,是因为业务特色嘛
- 最终楼主有解决方案嘛,求分享~
公共的组件,是否也可以跟公共依赖一样呢?封装成npm包后,通过script的方式引入并设置ignore?
公共的组件,是否也可以跟公共依赖一样呢?封装成npm包后,通过script的方式引入并设置ignore?
可以的
公共的组件,是否也可以跟公共依赖一样呢?封装成npm包后,通过script的方式引入并设置ignore?
可以的
那比如一些不方便封装成npm包的业务组件,比如依赖了axios、moment等第三方包的组件,我该怎么处理呢?是单独放子应用进行解耦?还是主应用传递给子应用?
那比如一些不方便封装成npm包的业务组件,比如依赖了axios、moment等第三方包的组件,我该怎么处理呢?是单独放子应用进行解耦?还是主应用传递给子应用?
这些组件,主应用直接挂 window 上,子应用能读取到,至于这些组件的依赖(axios、moment等),可以由组件引入
那比如一些不方便封装成npm包的业务组件,比如依赖了axios、moment等第三方包的组件,我该怎么处理呢?是单独放子应用进行解耦?还是主应用传递给子应用?
这些组件,主应用直接挂 window 上,子应用能读取到,至于这些组件的依赖(axios、moment等),可以由组件引入
主应用挂window上,那是不是子应用独立开发的时候,需要把主应用也运行起来
search 到这个 问题,想要讨论一下 公共依赖的版本是如何管理的,要如何控制公共依赖的升降级呢?
DllReferencePlugin+libDll.js
请问下楼主是否有了最终的解决方案,可以分享一下么
请问下楼主是否有了最终的解决方案,可以分享一下么
就主应用下发不是挺好的吗? 静态资源就cdn