9

flutter 小程序思路

 2 years ago
source link: https://zhuanlan.zhihu.com/p/412110037
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

flutter 小程序思路

halo 大家好,俺是 132,在过去一段时间里,俺主要做公司的小程序架构,经过我一波又一波的瞎捣鼓之后,小程序架构终于变稳定了

在这个过程中,我为了搞调试,为了搞编译打包,尝试了很多千奇百怪的思路,我深深的感知到,在公司里做方案,真的要懂特别多才可以

今天给大家介绍一种 flutter web 的方案,可以用到我在小程序中的一些经验

flutter 痛点:动态化

这个我就不多说了,相信每个做 flutter 的公司都在寻找热更新的解决方案,但结局应该都差不多:找不到的,啊哈哈哈

为了解决动态化的痛点,社区内可以说百花齐放,各种方案层出不穷

比如阿里的 kraken,美团的 flap 等等……这些方案基本上都属于 case by case,大力出奇迹的工作……

说实话,看着就头大(lll¬ω¬)

flutter web 痛点:包体积

于是,我们不得不将目光转移到了 flutter web,因为 flutter web 编译后是一个纯 h5 项目,所以天生适合做动态化

但……因为 webview 单线程的限制,h5 的体验通常不咋地

同时,flutter web 最终的打包文件会很大,仅仅是 hello world 就 2m

为了解决这一系列问题,我们得想办法做一套方案

flutter miniapp

其实优化包体积,和优化 webview 体验的方案有很多,但我比较擅长做小程序,因为携程小程序已经展示了一种近乎完美的链路了

小程序是双线程的,会对资源和每个页面的脚本引用做预加载,这就可以完美解决包体积的问题

同时,双线程的渲染是异步的,也可以做到秒开体验

也就是说,其他公司大力了很多年地效果,我们完全可以通过其他途径做到

但是虽然总体的架构是类似的,将同样的架构做到 flutter 中,每个环节都会有一些差异

我决定记录一下,也顺便重新思考

  1. trippal miniapp 架构
compiler(wxml/wxss/js => fre) => jscore => Mutation Records => webview

可以看到,trippal miniapp(携程小程序)的总体架构是将 wxml 等编译为 fre 代码,然后在 jscore 中跑

然后我们只需要在 jscore 中模拟 dom 子集,最终使用 Mutation Observer 收集 Records 发送到 webview 就可以愉快画图了

因为 fre 中使用的 dom API 非常少,所以模拟一个 dom 子集很容易,也就 200 行代码而已

new MutationObserver( mutations => {
	send({ type:'MutationRecord', mutations });
})).observe(document, { subtree:true })

2. flutter miniapp 架构

flutter 小程序的架构,因为它走官方的编译器,将 dart 编译为 js,所以模拟 dom 的方式已经行不通了

flutter build(dart => js) => hermes => Proxier => webview

因为 flutter 编译后的代码包含大量 canvas 代码,模拟一个 canvas 对象实在成本太高了

聪明的人已经想到了,没错,就是使用 fard 的思路,使用 Proxy 劫持 canvas 即可

const proxy = function (id) {
  const fn = function () {}
  fn.id = id
  return new Proxy(fn, objHandler)
}

const document = proxy(0)
const canvas = proxy(1)

使用这个思路,我们不需要模拟 dom,只需要收集指令集发送到 webview 即可

和 fard 一样,这个方案也只需要大约 200 行代码

但考虑到 flutter 的代码很复杂,除了 canvas 还有 web-component

customElements.define('flt-glass-pane', class extends HTMLElement {
  constructor() {
  }
})

这种 web-component 的注册,是没有走 Proxy 的,因为 jscore 端没有这个实例,所以这里需要扭曲意义

但无论如何,这个思路是当下最可行的思路了,哈哈江山轮流转,曾经淘汰的思路现在又用上了

另外,和 trippal miniapp 不同,flutter miniapp 我们不走 jscore 了,转投 hermes,这是 RN 自带的 js 引擎,也是 ctrip 本来就有的

比较有意思的是 hermes 支持跑 js 字节码,这块也可以作为后续优化

split chunk

其实 flutter 的 split chunk 我还是想做的,基本思路是使用 swc 对 dart 编译后的代码做一次 scope-hoisting 然后 tree shaking 掉公用的函数

这里有一个小技巧,就是打包的时候使用 O0 级别的优化

flutter build web --profile --dart-define=Dart2jsOptimization=O0

这样就可以得到一份未压缩的代码,但我看着一个 hello world 都要 10w 行,我哭了/(ㄒoㄒ)/~~看着又双叒叕头大了……

总结

思路确实是有的,但具体能不能搞得定,需要我花很长一段时间去研究

但是看 flutter 代码真的给我很多鼓舞,这群人真的太顶了,我一定要顶住压力

另外,之所以走 flutter web 方案而不是 kraken 或者 flap 的方案,是维护量决定的,我们公司基本都是单挑,所以会避开大力出奇迹的方案


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK