探寻框架设计中的平衡
Evan You on Vue.js: Seeking the Balance in Framework Design | JSConf.Asia 2019
不是单纯的翻译,有自己的理解。
Scope
Vue、React、Angular本质区别
-
Library vs Framework
-
Primitives vs Abstractions
-
Bazaar vs Cathedral
Small Scope
React偏左,内容少,上手成本低,十分灵活,因此生态繁荣,且团队维护成本低。也正因如此,后续学习成本高,因为React提供给你的太少了,必须去额外学习相应的、并且会不断变化的生态(如:Redux)才能构建合格的应用。
Large Scope
Angular偏右,内容多且完备,只需阅读官方文档就能得到你所遇到的问题的最佳解决方案,而不用到处寻找。缺点是上手成本高,为了实现简单的功能可能需要阅读大量的文档,而且不够灵活,如果官方给出的解决方案和开发者遇到的实际问题有细微出入,那到底该不该使用这种方案?最后,一个large scope的框架的迭代成本很高。
Progressive Scope
Vue处于两者之间,既可以像Large Scope类型的框架那样给出许多常见问题的解决方案(Vue-Router、Vuex),同时,开发者如果只想构建一个简单的应用,完全可以忽略以上部分,甚至也可以选用符合自身要求的路由器和状态管理工具而不是Vue的官方方案。
渐进式拥有两者的优点,同时也继承了两者的缺点。例如官方生态与框架本身高度集成,导致了维护成本高,同时由于官方方案的出现,开发者就不会很愿意去实现自己的方案,因此生态也不如Small Scope类型框架繁荣。
Render Mechanism
- JSX vs Templates
- Expressiveness vs Raw Perf
- Runtime Scheduling vs AOT
使用了虚拟DOM的框架(React)在左,基于模版的框架(Svelte)在右
JSX/Virtual DOM
- 优势
- 能够利用JavaScript的完整表现力
- 可以将视图视为数据。(一块视图被表达成了一颗虚拟节点树,一个JS对象,这个视图被称为组件)
- 可以在用户区定制使用视图数据(你能操控数据就能操控视图,数据是万能的,因此视图也是万能的)
- 缺点
- 性能开销。
- 每次组件树的Diff是很耗时的,而且和组件树的复杂度相关(而不是和可变节点数)。假设你有一颗庞大的组件树,里面的可变节点很少,可在视图更新的时候仍然会完整对比,浪费性能。(在Vue3得到优化)
- 动态程度过高,难以AOT优化。(校招的时候被面试官问到了)
- React使用了大量优化手段来提升感知速度(Fiber),但是调度本身也是基于运行时的,你可能得花一段时间来加载、执行这段调度代码才能用上它。
Templates
- 优势
- 没有Diff过程,只需要利用指令去修改变动部分,性能优秀。
- 不需要构建庞大的组件树和与之配套的方案,更轻的运行时。
- 缺点
- 不够灵活。模版语法的表现力很弱,在写一个复杂组件时会很麻烦。
- 需要花更多的时间来编译(构建时间长)
Vue
Vue基于两者之间,同时使用了模版语法和虚拟DOM,既可以利用JavaScript的表现力,同时也可以对模版语法做编译时优化(在Vue3做到了)。不过性能不及Svelte,因为Vue还是维护了一个虚拟DOM的Runtime,并且有些用户可能永远都只用模版。
State Mechanism
- Mutable vs Immutable
- Dependency tracking vs Dirty Checking
- Reactivity vs Simulated Reactivity
未深入讨论
The Balance
如何探寻框架设计中的平衡?真的存在完美的平衡吗?
想要构建一个东西的时候,人们都会往特定的方向优化。
-
如果你只想构建简单的应用,你可以用Svelte,它足够轻量,足够快。
-
如果你想构建大型应用,并且在意极限性能,你可以用Vue,它有强大的表现力,同时也可以使用直观的模版语法,并且有编译时优化。
-
如果你看中社区繁荣度,那就去用React吧。
The framework landscape is like a multi-dimensional space with multiple ever-moving entities, each seeking its own balance point.
每个框架都有自己的特点,如果你作为一个使用者,在挑选框架的时候,请了解每个框架的发展趋势与内部权衡,并与自己想要构建的事物的方向作对比,才能做出好的选择。