流行趋势
不知大家发现没有,自从2021年以来,无虚拟DOM框架/库/编译器获得了极大的瞩目,最为典型的两个项目:
- Svelte
- Solid.js
我们来看看他俩究竟有多勇:
(来自https://www.tecla.io/blog/top-js-frameworks)
可以看到Svelte去年一年在GitHub上增长的Star接近Vue,甚至力压老牌经典框架Angular!
再来看看这个:
满意度甚至超越React和Vue,(吐槽:Angular这满意度趋势…)
感兴趣程度同样霸榜,只不过这回刚好反过来:Svelte力压Solid,Vue力压React(越来越多的人对Vue感兴趣了哈)。Angular颓势已显,气数已尽了?别担心!下一个选项(Usage)让Angular来告诉你,什么叫你大爷永远是你大爷:
奇怪,感觉自己身边明明没那么多人用Angular,怎么肥四?这是因为调查对象主要以欧美地区为主(尤其美国):
母语为英语的人占多数:
年轻人为主:
这就很完美的解释了为什么Solid和Svelte的受欢迎程度会那么高,年轻啊!折腾啊!你要是五六十岁了(在中国应该没有这个岁数的程序员了吧)你也不愿意折腾那些乱七八糟的。
年轻不代表是新手,还是有相当一部分有经验的开发者参与调查的。
数据来源:https://2021.stateofjs.com/en-US/libraries/front-end-frameworks/
不过这些数据还不能证明Svelte和Solid已经成为流行框架\库\编译器了,有相当一部分叫好不叫座的,我们来看看npm的数据:
哎呀!暴露了暴露了,再来看看Google搜索量:
可以看到三大框架依然是主流哈,而且Vue和Angular的差距已经越来越小了,当然还因为有股神秘的东方力量屏蔽掉了大部分去Google搜索Vue的,不然我相信Vue的数据一定可以超越Angular的。
数据源自https://trends.google.com/trends/explore?cat=31&date=today%205-y&q=React%20javascript,Vue%20javascript,Angular%20javascript,Solid.js%20javascript,Svelte%20javascript
没想到对Svelte最感兴趣的居然是韩国人!虽然三大框架YYDS,但作为后起之秀并且在没有明显优势的情况下(综合情况,光写个Hello World确实谁也比不过Svelte)依然能够从三大框架嘴里分一杯小小的羹,并且还能够获得如此巨大的关注度,那就证明无虚拟DOM的趋势已经悄然兴起了。
为什么这玩意会成为一种趋势呢?有啥好处?好处就是性能!
什么?虚拟 DOM 不就是为了提升性能的吗?!是也不是,推荐读一下这篇:
[0]《网上都说操作真实 DOM 慢,但测试结果却比 React 更快,为什么?》
他们会火不是没有原因的,我们来看看他俩的性能:
可以用傲视群雄这四个字来形容了,Vue之前一直以高性能为傲,但被人超了怎么可能会甘心?毕竟Vue和React不一样,当数据更新时Vue是知道该更新哪个组件的,React不知道所以它只能用diff算法,没有虚拟DOM根本不行。那Vue干嘛也要来一个虚拟DOM呢?尤雨溪也是这么想的!
其实他早就有过放弃虚拟DOM的想法了:在尤雨溪发表的《Vue3的设计过程》(翻译版)一文中,尤大说:一种选择是放弃虚拟 DOM 并直接生成命令式 DOM 操作,但这将消除直接编写虚拟 DOM 渲染功能的能力,我们发现这对高级用户和库作者非常有价值。
那时候Vue3还没发布呢,Vue3的createRenderer就是利用虚拟DOM来实现跨平台的,但成天老是跨平台跨平台的,我们平时开发业务又有多少跨平台项目呢?
现在追求的就是一个轻量级,没有了虚拟DOM就没有了Diff算法,不仅可以不用运行一些无谓的计算,而且打包出来的体积那可真是轻上加轻啊!它不香吗?
但也不能完全放弃虚拟DOM啊,一方面虚拟DOM还是有它大展宏图的场景的。另一方面你直接把虚拟DOM删了,那些库怎么办?它们有多少是依赖虚拟DOM的API的呢?有多少组件库用的是jsx呢:
[1]《为什么 Vue3 的组件库都在使用 jsx/tsx?》
去掉了虚拟DOM的话,那些组件库是不是就用不了了呢?那咱们可以搞个模式出来嘛!
无虚拟DOM模式
首先咱们先把尤大在发布会上说的话(重点部分)翻译下,为了节省篇幅不重点的地方就不贴上来了:
主要的事情就是:我们想要探索一种新的编译策略
我们都知道Vue是一个基于模板的框架,即使你能用jsx能用虚拟DOM,但大多数用户还是会用template模板。
(挨个截图太麻烦了我就不截了,还浪费篇幅,我就直接写翻译了,感兴趣的话可以点进去视频链接[2]看)
由于Vue的大部分用户都用单文件组件来写代码,所以我们其实是有机会把组件编译成原生JS、CSS的。所以编译的这个步骤是有机会能让Vue变成一个超级编译器的!这将会很有趣,所以我们想要探索一下新的编译策略,这也是受到了Solid.js的启发。新的编译策略可以把template模板编译成命令式的DOM操作+响应式的setup绑定以代替虚拟DOM和render函数。所以想象一下,当我们写了一个这样的组件:
(此处省略一些废话:这是script setup语法、看这里有个button按钮、我们给按钮绑定一个响应式的值之类的话)
我们生成的将会是这样的代码,生成出来的代码量非常少,目前的想法是我们过一遍虚拟DOM树然后生成真实DOM的操作。我们会在编译期分析template模板里的HTML的结构并将其字符串化:
为了能让打包出来的内容最小化,去掉了结束标签以及各种绑定的属性。然后再生成一个cloneNode:
通过分析得出哪些属性是响应式的,把它们都放在effect里,再绑定事件,全部都是非常好理解的DOM操作:
(这不比Svelte生成出来的那一大坨好多了?)
两种模式
这里的两种模式指的并不是虚拟DOM模式和无虚拟DOM模式这两种模式,而是无虚拟DOM模式下还可以继续再往下细分出来两种模式:
组件模式
比方说你现在手里已经有了长期维护的Vue3项目,你要是直接换成无虚拟DOM模式那肯定是要出问题的,所以可以采用组件模式来精确控制哪些组件不需要虚拟DOM。
比方说你的项目中采用了尤大推荐的naive-ui这个组件库,我们打开一个比较常用的组件Button来看一下:
tsx结尾,那虚拟DOM算是没跑了。不过tsx也照样可以给改成生成真实DOM的函数啊,solid.js不就是这么干的吗?其实理论上来说确实是可以做到的,我们点进去再看一眼:
这里用到了h函数,这个函数是专门用来生成虚拟DOM的,假如你把项目全部换成了无虚拟DOM模式同时这些库还没来得及跟进的话,那肯定是不行的。
所以你可以控制,你哪个组件里没用这个组件库,你再给这个组件单独的一个编译策略(无虚拟DOM模式)。
既然有组件级的那就肯定有应用级的,比方说你想开发一个UI高度定制化的H5活动页。
一般来说这样的页面不会用组件库,都是自己写样式。另一方面这种活动页当然是越小越好,越快越好啦!那么此时你就可以采用全局无虚拟DOM模式。
怎么感觉这是在抢Svelte饭碗呢?我看技术论坛已经有人分享了自己用Svelte来开发一些小页面的文章了,这回再有什么性能跑分之类的评测Vue应该不会再输给Svelte了(看情况,组件越少Svelte越占优,反之则Vue占优)
机遇与挑战
最近前端可谓是越来越卷了,你要是去面试稍微高级点的岗位的话,估计很可能会问你Vue怎么编译的两种模式了(即使你并不感兴趣)。
但我发现很多人对自己做一款组件库非常感兴趣,从文章列表里看一下究竟有多少组件库相关的文章就能够一探究竟了。而且很多教大家搭建组件库的文章也是点赞量非常高,还有很多文章推荐自己做出来的组件库。
只可惜大部分个人做的组件库都是孤芳自赏,没几个人用。一方面的个人开发者可能随时删库跑路,不稳定。谁知道你写的那玩意有多少bug呢?另一方面大家也更愿意用Star非常多的组件库,证明其稳定。
所以大家如果想从主流组件库那里分一杯羹的话还是非常困难的。那现在这个无虚拟DOM模式是不是就是一个千载难逢的大好时机?不过我个人依然感觉希望不大,因为那些主流组件库肯定会立马跟进,搞一款无虚拟DOM适配版。
不过不管怎么说,我对这个实验性特性还是非常期待的。因为这个编译策略编译成web components很可能会是一个非常不错的选择,总之,期待无虚拟DOM的到来!
文章链接:
[0]: https://www.zhihu.com/question/31809713/answer/53544875
[1]: https://www.zhihu.com/question/436260027/answer/1647182157
[2]: https://www.bilibili.com/video/BV12S4y1e7pn?p=1&share_medium=android&share_plat=android&share_session_id=4e2c7597-7fa7-4e0a-a098-5e0aa675b035&share_source=WEIXIN&share_tag=s_i×tamp=1655041421&unique_k=nLvKgzv&vd_source=3490d817b36fc42ec9a252b6cd0d6baf