7

2021 · 小程序底层架构

 3 years ago
source link: https://zhuanlan.zhihu.com/p/373958625
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

2021 · 小程序底层架构

✅跪在床上娇喘,❎隔着网线叫唤

halo 大家好,俺是 132,今天给大家带来一篇小程序底层架构的文章,之前俺在 @前端早早聊 分享过一次,但是很多人没有去听,所以今天特地补一篇

不变的是双线程

很多人无法理解双线程是个啥原理,其实很简单

function Component(){
  // 这里没有其他逻辑啦
  return <div>{data.aaa}</div>
}

如果你的视图,都是这种空组件,或者都是 html 标签,那么渲染是很快的

真正阻塞的逻辑是 js 逻辑,对于小程序来说,就是各种函数,比如

Page({
  data:{  // data 是需要共享或传递的
     aaa: 0,
  },
  onLoad(){
    // 这里才是阻塞的
  },
  bbb(){
    // 这里也是阻塞的
    wx.navigateTo({
       // 这里还是阻塞的
    })
  },
})

所以双线程其实就是这么回事,它把视图层和函数分开两个线程

  1. 视图层只负责渲染空组件,空标签
  2. 逻辑层需要执行函数,然后修改 data

serde or 内存共享

大家已经了解了双线程的模型了,这两个线程有需要共享的东西,也就是 data

比如这样:

Page({
  data:{
    count: 0
  },
  add(){
   this.data.count++
  }
})

当我在逻辑线程中执行了 add 方法,修改了 data,那么这个 data 就是直接修改了内存的引用

理论上将,在视图层如果可以拿到这个引用,拿到新的值,什么时候更新,是批量更新还是立即更新,都无所谓了……

那么问题来了,怎么拿到 data 呢?

过去,人们喜欢序列化 data,然后通过类似 message channel 的方式发送到主线程

// 主线程
window.addEventListener('message',(e) => {
  const data = de(e.data)
})

// 子线程
self.postMessage('data', ser(this.data))

在 serde 的过程中,会对引用类型进行映射,比如使用 id

但是 serde 的性能一直饱受诟病,尤其是 1202 年了,自然有更好的思路,那就是内存共享

主要思路就是使用 sharedArrayBufferAtomics

这俩是 es2017 的新特性,专门用来 v8/worker 进行内存共享的,它比序列化通信,更符合小程序的场景

值得一提的是,deno 和 RN fabric 也是这么实现内存共享的,但 deno 1.9 放弃了这种做法,转而使用了 serde 的方式

那是因为 rust 的 serde_json 可以直接序列化 v8 的值,性能更好

所以到底是使用 serde 还是使用内存共享,是由具体的场景决定的,像 serde 对于 deno 就更快,对 RN 和小程序就更慢

除了性能,内存共享也更符合小程序的语义,共享 data,简单粗暴

no runtime 还是 vdom

看过我去年的分享的都知道,我首次提出来小程序使用 no runtime 的思路更好

有很多理由:

  1. 小程序不是 RN,它应该最小资源分配(内存)
  2. 小程序的 template 不可能不编译,既然编译就可以做到 no runtime
  3. 小程序使用了双线程,runtime 是多余的负担

还记得我们的视图层是干嘛的来着?

渲染空组件

视图层的终极形态应该是纯空组件,但这是不可能的,像 scroll-view,picker 这些组件的逻辑不可能很轻量的

此时再使用 vdom 这种,视图层产生阻塞的机会就更多了,虽然 fre 有时间切片,但还是违背了双线程的初衷,达不到最佳形态

所以,no runtime 的形态很赞了,尤其是 svetle 成功证明这种可能性

不了解 no runtime 的框架,可以看我这个回答:

其实我也写了一个 asta,就是为了双线程架构服务的

web-component 和 同层组件

刚刚我们谈到的,有一些组件不可能轻量,scroll-view,picker 等等,那么怎么办呢?

此时 web-component 就上场了,因为 沙雕 dom 其实有个好处,那就是隔离主 dom 树

1202 年 web-component 确实是彻底凉了,但是

凉了只是说它不可能替代 react 这种框架,不太可能成为主流,不意味着它不能处理特殊场景

你知道吗?浏览器原生的 video 标签就是 web-component

小程序同层渲染原理剖析 | 微信开放社区

微信的同层渲染是使用 embed 标签和 webPlugin 实现的,实际上浏览器过去的 flash,pdf 也是用的这种方式

俺直觉告诉我,web component 应该也可以做同层渲染,不然 video 是咋做的,只是还没找到方法,如果你找到了,请一定要告诉我,蟹蟹

总结

以上,就是关于小程序架构的最新文章,俺之前讲了许多了,但是每次都有新的变化和思考

另外,虽然我在公司里也做同样的工作,但本文提到的,内存共享,no runtime,同层组件,都不太可能落地

但是如果你公司也要搞小程序,而且全新的,那么我说的这些就是很好的选择了

最后给前端早早聊打一下广告的,微信直接搜公众号就好

俺很少技术分享的,如果错过了,就只能看俺好短的小作文啦


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK