如果没有湮灭,那就继续发光 | 掘金年度征文

976 阅读11分钟

2019,还能忆起的那些事儿

回首2019年,感慨真的过得好快,技术上没有产生非常大的变化,我关注的点比较窄,通常只会敏感的记住一些和我工作有或多或少直接联系与间接联系的事件,写下这篇文章时,脑海里还能回想起的关心点大概如下了:

  • 一直关注的deno据说明年可能发布1.0版本了
  • flutter以势不可挡之人气火爆全球,顺带还救活了dart,让这门语言又有了继续存在的理由
  • webassembly成为W3C标准,给前端的发展带来了更多的可能
  • fb除了重构整个react-native自身的架构,还发布了新的js引擎Hermes,用于提高react-native的性能,看起来rnflutter之间还会摩擦出不少火花
  • react发布16.8支持hook,将函数组件带到一个新的高度,同时后续将支持的异步渲染,时间切片等功能,这些特性都是围绕着开发者体验和用户体验而打造,也为巩固react在前端界的地位继续添砖加瓦
  • v8引擎继续提速,每次新版都带了各种指标的大幅提升,nodejs也因此受益,总之一句话,新版本肯定是更香的😀
  • vue3的前身vue-next正式公布源码,带来了全新的基于函数的组合型api,掀起了不小的波澜
  • svelte 3发布了,一个提倡compiler as framework的框架,用最原始的htmlcssjs写现代前端,让前端开发套路又多了一种选择,当然了它号称的去掉runtime打包体积更小也引起不少网友讨论,即书写复杂的应用时,svelte的打包体积会不会超过其他3大框架呢?这个临界点是多少呢?

以上就是这一年我主动关心的话题了,其他的被动接收的要想起来就感觉比较混乱了,诸如跨端应用云函数无服务云IDE垂直深度的工具化等等一对名称都会时不时的出现在各种场合,总而言之,前端的水依然非常的深,入坑的小伙伴要挑准几个方向,然后齐头发展,而不要强求全方位贯通,这是不可能滴😀,各自在自己擅长的领域发光发热,构建一个稳定繁荣的生态而实现共赢。

2019,Concent顺利从构思落地为现实

上面提到的那么多事件,只是整个前端业界热闹的一角,看完它们相互角逐,也该回顾下自己在这一年的建树了,作为一个多年react&node开发者,在这个时间点还是想凭吊一个已经死去多年的游戏:【龙魂契约】

这是一个2014上线的类部落冲突的手游,是它带领着我进入到nodejs的后端世界,进而爱上了js,然后又顺着接触到了react,这一入坑就是4 5年,如果没有这款游戏的引领,我现在点亮的技能树又是什么样的呢,虽然我不相信万事万物冥冥中自有注定,但还是总会陷入到好奇那些如果都变成了现实,那么现在又是哪般风景的沉思里,可能只有多重宇宙能够解开如此复杂的真相啦😀

作为react使用者,也经历过和大家相似的路程,折腾过webpack配置,开始学习es6语法,开始了解到状态管理这些概念从而进一步的接触到了redux,开始尝试着从各种rc-component库里挑选自己想要的组件到直接开始使用material-uiant-design等类似的企业级ui库,慢慢累积属于自己专属的各种boilerplate,当然了我猜也有不少小伙伴甚至会基于cra定制自己的cli工具链,在学习和使用react的路上,大家都或多或少的摸索并分享过一些最佳实践,某种程度上react社区的繁荣也有小伙伴们不停折腾的功劳😀

爱折腾的我在2019年的某个深夜,盯着屏幕上基于antd-pro的代码陷入了深思,我看着满屏的*yield真的充满了不喜欢的感觉,同时也仔细查看了rematch代码,对effect逻辑块里还存在着this也是不喜欢,我知道它们都是基于redux而封装的,绕不开一些规则,只是隐藏了更多繁琐的细节,让我们开发更简单而已,其他的状态管理我也通过各种渠道接触和尝试了,诸如mobxunstated等等,我都觉得它们把react变形了,能不能有一种方式让状态管理呼之即来挥之即去呢,我需要的时候它就存在,我不需要的时候它就消失,这就意味着我们对代码要做到最小程度的入侵,才能实现这个目标。

于是我敲起键盘,撸出两个state一样但是渲染不一样的class组件,在它们的constructor里获得this,绑定在window.ref1window.ref2上,当我调用了其中一个组件实例的setState时,也将状态传递给另一个组件实例的setState句柄触发其调用,这样看起来一个超级简单的状态共享就完成了,所以我的第一个目标就很明确了,劫持组件实例的setState,将其赋值到到实例的另一个属性reactSetState上,这样原始的setState得到了保留,接着我替换setState的指向,让其指到我们自己的实现函数,它拥有状态分发的功能(即调用所有相关实例的reactSetState),这样的话,我就达到了0入侵的代码改动提升组件状态为共享状态的目的了。

before

after

依赖标记

接着新的问题诞生了,如何让自己实现的setState正确的分发状态到各个实例上呢?我思考了很久,需要先抽象一个模块的概念,模块下拥有state等其他的定义选项,然后在组件标记模块名就好了,因为我的设计是要将模块state直接合并到实例的state上的,为了满足组件能够消费多个模块的数据,我需要为每个实例构建一个上下文,这样其他模块的状态直接打入到ctx.connectedState.{moduleName}上,moduleName天然的承担了命名空间的作用,防止不同模块变量名相互污染的情况产生,这个过程我称之为依赖标记

标记不只是标记模块名,还可以标记模块下关心哪些stateKey的值变化,这样就可以非常细粒度的控制渲染范围,相比运行时动态的收集变更依赖,省去了劫持原始数据转变为可观察代理对象的初始化开销,更符合react本身的不可变原则了

引用收集

我们知道React通过给组件实例附加_reactInternalFiber属性实现Fiber特性,基于Fiber的链表式树结构可以模拟出函数调用栈,实现了hook,suspense等特性,受此启发,我同样可以采取类似思路,给所有需要实现状态管理的组件实例附加ctx属性,在这上面记录了组件定义阶段标识的模块和观察依赖等元数据信息,从而建立起一套独特的和业务紧密相关的更新调度机制。

看起来这些组件是相互孤立的,但其实它们内部的模块和观察依赖等元数据信息已将它们非常紧密的记录在了我自己构建的全局上下文里。

状态分发

全局上下文主要用于分类和索引所有的组件实例

第一层map

第二层map

任何一个Concent组件实例修改状态的行为都会携带有模块信息,当状态改变的那一刻,实现精确更新就非常容易和自然了。

至此完成了整个Concent的架构设计,经过在项目里使用过程中不停的收集反馈并做细节优化, 觉得到了可以分享到社区的时候了,同时为了体现Concent组织代码的优越性,实现了一个antd-pro-concent,后来中途受到Vue Function-based API RFC一文里setup的启发,在concent里实现了对等的setup特性,更让我觉得这一年所有为之付出的努力都是值得的。

开源是一个需要长期付出并且能够忍受默默无闻的过程,这一点我深有感触,特别是状态管理以及被reduxmobx统一了不可变和响应式两个方向的局面下,发起Concent的意义何在?

我结合Concent自身的特点,定义了一个明确的目标,那就是在整合和吸收redux&mobx的优点的同时,在运行时就建立起一套更优的更新调度机制,让开发没有心智负担,书写更少,做得更多

  • 遵循react不可变的原则,彻底面向函数式编程
  • 支持跨多个模块&key级别的订阅粒度
  • ReactDomTree渲染期间只产生干净的视图组件,消除层层多余的功能增强容器组件
  • 业务逻辑和ui渲染分离更优雅,函数组件和类组件享有统一的api调用,没有割裂感
  • 支持至上而下的统筹性开发,也支持至下而上的渐进式的书写应用
  • 更弱的代码入侵,更优的代码组织结构,更好的typescript支持,更高的渲染性能

我知道这些标语不能够靠喊口号,linux之父曾说过talk is cheap, show me the code,所以只要有时间就会不停的在stackblitz上书写示例,回首一看,不知不觉写了几十个了,都是为了展示更炫酷的reducer原子化拆分和组合调用,更易于逻辑复用的setup等等其他很多很多有意思的功能。

但是stackblitz上并没有任何的数据可以让我知道到底有多少人浏览过,这种感觉其实让我感觉蛮孤独的,就像玩一个单机游戏,没有互动,只有npc和升级,除了感动自己再无其他。

这时发现了CodeSandbox这个在线ide站点,它提供了一个项目访问量的数据,于是我精心的在它上面书写了两个concent应用,一个基于js,一个基于ts,ts版本同时还发布源码到了git.

一个月过去了,获得了1000多的浏览量,我知道这一点浏览量相比Dan大神那些关于hook&useReducer等动辄几百万的浏览量简直太渺小太微弱,但是内心觉得不再孤单,有那么一小部分人看过了示例,就是我继续更新concent的最大动力

随后我在[Concent文档主站]加入了数据监测,以统计站点浏览量,偶然有一天发现了一个奇怪的拐点,突然有了那么一丢丢的上升,你知道的,对于这种边缘项目,一点点上升对于我来说都是很敏感的

浏览量从个位数上升到两个数,在20到40之间浮动

于是我打开git,发现这几天突然涨了100颗星星,心里觉得好激动,打开Stargazers列表,发现出现拐点的那一天有一颗星来自我的偶像, avalon.jsanu.js的作者司徒正美

这是我2019年以来最快乐的一天,因为这一颗星星,我觉得我的付出并没有那么的不堪,我的努力终究还是得到了一点认可,让我更加坚定了Concent前进的道路。

如果没有湮灭,那就继续发光

end

2020,还有好多Concent的建设工作要做,文档国际化,cli工具提供,响应式和不可变共存的可行性探究等等,让我们一起在大前端这个伟大航道上,乘风破浪,砥砺前行吧!

掘金年度征文 | 2019 与我的技术之路 征文活动正在进行中......