-
Notifications
You must be signed in to change notification settings - Fork 455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
多页程序里面,miniprogram-app、每个入口页为webpack的entry,module内部的单例变量机制失效,如何破? #71
Comments
这个不是很理解,可以给个具体的场景例子么?
这个目前确实是按页面隔离的,我记一下,后面支持下各个页面的 cookie 互通。 |
具体的例子就是:
app.js
pageA.js
列如目前的vuex是页面级的,而无法做到全局的,因此没有全局的状态管理机制。 是否可以考虑全局一个webpack的runtime?
其它生成的page.js:
类似上面这样。目前如果用上述的方式,page二次打开会有点问题,可能跟router有关,还没有具体调试。对vue的runtime不太了解,不知道全局一个webpack的runtime能否支持。 上述方式对web没有什么破坏。小程序JavaScript里就一个运行时,目前webpack的编译生成多入口,多个runtime,实际上会导致page与page、以及app之间的js module隔离。 |
@huadong 但是页面间的设计本身 runtime 应该隔离的,就如同浏览器中不同 tab 一样,小程序页面本身的设计也是如此,全局数据通常也是通过 getApp 来进行共享,不然页面间可能会有互相干扰出现奇怪的问题。 所以你的需求其实是需要页面间通信的方案? |
这是一个非常值得讨论的问题。从目前微信小程序的开发规范来看,整个小程序是一个JS的运行时,对于module的引用遵从js的规则,详见:模块化。此规则的存在,让大家可以实现全局的状态管理,可以使用redux、vuex之类的。只不过这样去使用,开发者需要谨慎控制页面之间的对象引用关系,但是这样大大提高了代码设计的灵活度和复用性,包括对成熟的开源代码的使用。 不过,对于subpackage的使用,规范有严格的要求:
而目前kbone因为使用webpack独立的runtime机制,进一步增加了隔离,相当于主动削弱了小程序代码支持能力,这会使得kbone的灵活性和扩展性降低,不容易被选用于大规模的生产中。 这里面有个对标问题,小程序是对标H5,还是对标APP。目前原生态小程序可以对标到APP的开发上;而kbone的封装直接对标到了H5上了。kbone从设计思路,代码、文档行文等都非常优秀,但如果仅仅对标到了H5上,就太可惜了。 关于这个问题,#46 里面也提到类似的观点。 |
整理一下原生小程序的实际情况:
因此:
实际上,kbone在设计上也使用了这个能力,比如cache的管理,小程序全局的config等等。 |
我明白的你的诉求了,你是希望:假设在页面 A 和页面 B 都引入了 c.js 的情况下,这个 c.js 是运行时也应该是同一个,页面 A 调 c.js 存入的变量在页面 B 是应该是可以正常获取出来的。 不过这里我还是不能将所有页面改成在同一个 webpack 包裹内,kbone 一开始的设计初衷确实是以实现 Web 端写法为目的的,Web 端不同页面的共用模块是隔离的,所以不能偏离这个设计。举个例子,有个页面比较特殊,需要扩展 Vue 原型,但是其他页面不用,如果在同一个 webpack 包裹内的话可能其他页面也被做了不需要的扩展。 所以换个思路来,如果我提供一个页面间通信方案和共享存储区域能否解决你的问题?比如我注入一个 g 对象,不管在哪个页面拿到的 g 对象都肯定是同一个。 |
基本是这个意思
这个问题最重要,这是kbone的对标定位问题。不过“写法”和支撑能力却是值得思考的问题。比如说很多“语法糖”提高了代码编写的效率,但并没有限制编译后代码的运行能力。 小程序的page和web端的page是有区别的,有时候感觉更像vue在router下的一个component,是介于component和web page之间的感觉。 webpack对于多entry打包,并没有强制要求每个entry必须是一个隔离的包裹,是允许多个入口点引入到同一个页面中的,因此有了对runtime的独立打包配置:optimization.runtimeChunk
你提到的Vue的扩展是一个很好的需要隔离的例子。但如果我们引入axios呢,一般我们会在app.js统一配置axios的adapter、interceptors等,然后每个页面直接require axios,直接使用就好了,而无需每个page都要对axios进行一次初始化配置,大家共享一个实例就好了。当然可以把app.js初始化的axios实例通过globalData进行传递,但这个使用就不那么友好了,而且类似这种共享对象实例还不少。 这是一种机制问题,kbone框架本身使用了这种机制,然而对page的约束限制了这种机制的使用;但是使用kbone + webpack打包后,所有代码都无法逃离这个框架。也许使用自定义组件可以? 或者有没有一种方式,可以把一些代码、和指定的第三方依赖包打包放在全局使用?
这里涉及到的其实是个软件工程问题,如果单纯的实现页面通信或者数据共享,直接用globalData就可以了。主要是同一个js module在页面间的唯一性机制没有了,很多第三方包的使用会有问题。无法直接使用了。像kbone那样连Event、Node等都从0造起,对大多数公司和团队来说是做不到的。 |
@JuneAndGreen 再举个例子,你看看如果用kbone去做一个多tab的小程序,实现类似QQ音乐APP的底部浮动播放器的功能,会有什么不便利的地方。 功能细节要求:
|
小程序在 kbone 跨页面使用 Event 库也有这类问题,一个页面监听的事件,另一个页面触发也不会生效的。我能想到的就是像这类需要跨页面使用的库,只能通过 getApp 挂载到小程序全局上,再来使用了。但对应到 web 的多页,又没法找到合适的办法进行兼容。 或者说官方是否有针对这类情况提供一个推荐的兼容解决方案? |
主要还是最开始的前提问题,因为 Web 端页面是隔离的,所以肯定不能破坏这个隔离的机制。你这种应该是单纯想用 web 语法来编写小程序,所以更重视小程序的设计而不是偏向于 Web 端的设计,这个得思忖一下有没有其他的思路才行,比如你的建议:把部分文件打到公共 runtime 之类。这个我记录一下。 |
这两天尝试修改了一下kbone的webpack插件mp-webpack-plugin,使用optimization.runtimeChunk = single进行打包,调整了一下webpack的runtime引用方式,在app.js引入runtime,各pages.js复用这个runtime,总算进一步理解kbone的window囚笼了:
这里的:
由webpack bundle + window 组成的囚笼确实很牢固的,虽然可能可以通过webpack的optimization.splitChunks进行深度的打包配置,再加上使用mp-webpack-plugin进行bundle拆离引入,但可能还是很晦涩。这让我想起了GitHub CTO Jason Warner说的: 这意味着在kbone当前的设计下,很难实现全局的状态管理机制,类似redux、vuex、mobix之类的。
算来算去,kbone有点“鸡肋”了,感觉有点可惜。 其实我希望的不是单纯用web的语法来写小程序,而是希望能在写小程序的时候可以引用海量的、成熟的、可复用的项目代码。 |
这样理解不对,kbone 本身是作为适配器一般的存在,来支持原本的 Web 端代码在小程序运行,Web 端代码是按页面粒度分离,所以到小程序端亦是如此实现。 但是想两个平台完全互通兼容目前来说确实是做不到的。事实上在 Web 端两个页面的全局状态也是不互通的,除非是 spa 中的单页切换,页面不刷新就可以保留全局状态。这也就是设计问题,小程序的页面对标了多页 Web 应用的页面,而不是 spa 中的单页。 如果想将 spa 直接对标一个小程序,这是另一种不错的设计思路,但是孰优孰劣其实没法直接衡量,也许后面可以尝试给出另一种插件来实现这个设计。 |
我们就是正在尝试采用该方法,小程序的多页对应 Web 的 SPA,这样可以让两个平台都有比较正常的开发和使用体验。 @Ryqsky |
让10多亿人内置kbone的核心组件,同时在小程序社区进行了大力的宣扬,而且围绕kbone还做了很多的支持性开发,难免对kbone有所期许。因为对于已存在的Web端代码,其后端一般是连着公众号的业务代码,按目前微信的技术生态体系,它的迁移还是需要颇费一番功夫。与其迁移,不如重写一个小程序版的;而且好多微站都是技术服务商提供的开发。
反过来,按小程序目前的runtime设计,更适合对标的就是SPA。我觉得今天微信小程序所获得的发展,和小程序类似SPA的开发技术、同时在用户操作上更贴近APP的习惯是分不开的。相当于复用了熟悉SPA技术的程序员,解决了H5微站不那么友好的用户操作问题。 Kbone的整体设计思路、代码行文可圈可点,通过简单的webpack打包配置和mp-webpack-plugin的少量修改,可以实现webpack的runtime按全局配置还是按照pages独立配置。当前通过createPage()封装调用,使得page+window+document是捆绑的;如果修改kbone的miniprogram-render(当然这么一改就失去了微信小程序的内置😭),是不是可以实现SPA的对标?拿Vue举例,小程序的多pages相当于SPA里面的多Vue实例(多root)。 对前端技术没太多的研究,应该还有更好的实现方案。还是那句话:“kbone当前的支持能力,有点可惜了。”期待它的进一步发展! |
跨页 cookie 已支持,即所有页面 cookie 共享一个存储。已发布在 [email protected] & [email protected] 上,相关文档:https://wechat-miniprogram.github.io/kbone/docs/config/#runtime-cookiestore |
cookie 这么parse会有bug的:
我提交一个PR吧 #81 。 |
此 pr 有问题哈,cookie 如此解析主要是要对齐 document.cookie 的 setter 方法。 |
腾讯小程序的不同版本API也会有Bug。出现过第一下不是key=value的版本。 |
如果是微信小程序/公众平台/开放平台这边提供的接口出现这样的问题,可以到 https://developers.weixin.qq.com/ 社区这边提问哈,把规范甩上去。如果是其他应用提供的接口,估计得去相应的反馈渠道去反馈了。 |
我的看法 确实对于大多数人来说,小程序对标的是Web的单页 市面上的框架也好,插件也好都是把改小程序改造的更像单页应用。这个是大家默认的方向和事情。 变成多页的好处没有,倒是局限变得多了。这一点更难理解,明明大部分情况下使用单页就是为了优化多页的体验,现在又变回去了,只为了做到规范的「隔离」? 所以我也很矛盾,因为一方面如果只站在技术的角度,我觉得kbone 的做法合情合理,也本来就是这么做。 |
对标问题:
应用场景不太一样。目前大家都是对标着APP开发小程序的。 |
@JuneAndGreen demo22中的共享vuex state的方式存在一定的问题: 一个是内存泄漏问题: 一个是响应式对象的__ob__属性相互覆盖问题: 比如把一个已经被定义成响应式的对象赋值到state的某个属性时,因为vue内部是通过instanceof Observer来判断的 比如调用数组的push,vue通过改写数组push,unshift,splice方法来实现数组这类变化的监听,只有__ob__属性所属的页面才能收到变化的通知。 |
@hanjunspirit 明白,确实可能有这个问题,先前写这个 demo 考虑不够周详。我看看能否提供一个工具方法来处理这个问题。 |
内存泄漏问题,目前暂时没有其他更优雅的方法,还是比较建议每次页面进入时刷新 state 的方式来干掉其他页面加入的 getter 和 setter。具体可参考 demo22。 |
使用webpack进行编译,对于多页应用,miniprogram-app、每页一个入口点,打包后module的单例变量机制失效。
这导致多页程序的页面之间完全隔离,如同浏览器打开了两个独立的窗口(比tab窗口还独立),不仅如此,目前cookie的写法,page之间无法共享cookie。因此:
上边两点约束,kbone基本无法用于多页小程序开发,这个如何破 @JuneAndGreen ?
The text was updated successfully, but these errors were encountered: