rotter:react 转 flutter 新思路

更新日期: 2021-08-10阅读: 1.5k标签: 思路

因为在公司里一直维护小程序,然后由于我重构了编译器,所以小程序会进入一段维护期,不会再大改了

这段时间我在寻找新坑,我们公司有个坑一直没人做,也就是动态 flutter,支持热更新,支持预加载,支持分布式开发

社区内的方案

框架架构优点缺点
mxflutter使用和 flutter 一致的 js api,构建和 flutter 一致的 widgets tree成本最小,心智负担最低必须和 wdigets tree 完全对应,语法上存在限制
flugy使用 widgets 模拟 dom成本适中成本较高,不能完美模拟
kraken直接在 render object 层模拟 dom抽象比较好成本最高,大力出奇迹

以上,是目前市面上最主流的三种方案,除了 mxflutter,其他两种方案都去模拟 dom

说实话我不是很喜欢模拟 dom 的思路,尤其是在 dart 这样一个语言中,runtime 太重总归不是好事

我一直认为,好的架构,它的心智模型一定是足够简单的

所以如果是我,我更喜欢 wxflutter 的思路,但 wxflutter 的语法确实存在限制,如果我们有办法用 jsx 生成一颗静态树就好了?

能不能做到呢?

答案是:当然能。

静态 jsx

flutter 的 widget 是完全静态的,所以我们使用 jsx 模拟是非常简单的

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Demo"),
      ),
      body: Center(
        child: Text('Hello Flutter'),
      ),
    );
  }
}

用 jsx 描述,就是

<Scaffold>
  <AppBar title="Flutter Demo" />
  <Center><Text>Hello flutter</Text></Center>
</Scaffold>

静态 jsx 很容易做到,但是问题来了……

如果走默认的 jsx 编译器,则只能编译出下面的结果:

{
  Scaffold: fn(),
}

只有执行这个 fn 才能获得接下来的子树,这可不行,所以现在的难题变成了,怎么编译 react 组件为静态对象

react 组件静态化

假设我们一个 react 组件,长这样:

function App(props){
  const [count, setCount] = useState(0)
  let a = 0;

  return <Scaffold>
  <AppBar title="Flutter Demo" />
  <Center><Text onPress={() => setCount(count+1)}>{count}{a}{props.b}</Text></Center>
</Scaffold>
}

我们编译器使用一种反向编译的技术,从 return 的 jsx 中分析变量来源

则这段 jsx 中有三种类型的变量

from hook:count, setCount
from props:b
form self:a

那么编译结果就很简单了:

[
  ['count', 'setCount'],
  ['b'],
  ['a'],
  ['Scaffold',{'onPress': 2},['AppBar'...]]
]

经过这一波操作,整个 react 应用不再有动态的东西,它没有可执行的组件,也没有动态的语法,它会得到一棵高度优化的静态树

我们将这棵树传递到 dart 端,调整一下就可以变成 widgets tree 了

线程通信成本

无论如何,这还是一棵树,传递它如果走 json 的序列化和反序列化,性能肯定很差

解决方案其实很简单,想办法绕过 js,dart 直接和 js 引擎通信即可

但这块我还没有做,所以未必能找到方法,如果找不到,则只能退而求其次,走二进制的序列化

总结

我们没有选择在 runtime 模拟 dom 的方案,也没有使用 js 生成 widget 的方案,而是选择 react 编译生成 widget 的方案

框架方案优点缺点
rotter将 react 编译为 widget心智负担小,react 标准仍然存在限制,但可以通过编译器进行 lint

这里的重点工作在于对 react 组件的编译,将其编译为一棵静态树

当然,这样做也有缺点,就是我们不得不将 react 组件作为完全静态的字符串去对待,所以限制也存在

但我坚信只要编译器设计地足够好,虽然无法覆盖 100% 地场景,但可以提供完善地编译器检查,和 lint

原文 https://zhuanlan.zhihu.com/p/397681827


链接: https://fly63.com/article/detial/10621

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!