前言大家好。我是爱分享的前端老头杨存。近两年,国外出现了两个前沿框架Svelte和Solid。你可能工作比较忙,不太关注他们,但是t他们却有后来居上的意思。再来看看github上的star数:7月份的掘金开发者大会上,Vue的作者尤雨熙在直播分享中多次提到了SolidJS和Svelte。是什么让开发者如此钟爱它?又是什么让友达如此关注他们?我们应该花时间研究和学习它们吗?文中将带大家感受这两个框架的魅力,并发表一些个人看法。欢迎朋友拍砖!已经建立了相应的学习群,我会陆续发布学习文章和视频。欢迎有兴趣的小伙伴加入:关注公众号“村长学习前端”,分别回复“苗条”和“扎实”。同样的开发范式应该说近三年最火的前端开发范式非ReactHooks莫属。ReactHooks已经完全取代了类组件。Vue3也终于确定了从原来的Class风格到类似CompositionAPI。今天要说的两位主角也不例外,都是机能风格。应该说是ReactHooks引领了创新,启发了众多框架启用新的范式,但同时解决ReactHooks各种问题的却是蓝色的。以下是三个竞争者:Vue3、Svelte和SolidJS。Vue3大家都很熟悉,我就不多说了。这里主要体验一下Svelte和SolidJS是如何做组件逻辑表达和逻辑复用的。组件逻辑表达Svelte3的作者RichHarris曾经说过Svelte的组件编译逻辑是受ReactHooks启发的。然而,由于Svelte组件构建在HTML之上,她看起来更像Vue。同时她更优雅,我们没有看到像letcount=ref(0)这样的反应式语句,当然也不需要count.value++。我们没有看到template之类的标签,就好像我们在写HTML页面一样!下面我们用Svelte写一个countercase,Counter.svelte:countis{count}作为Vuer,您会为这些变化学习Svelte吗?显然不够!我终于习惯了ref和.value,现在感觉没什么大不了的。但是作为一个新人,如果我是第一眼看到Svelte,我一定会爱上她的!优雅的她,让人一见倾心!Solid友达是这样描述SolidJS的:语法类似于React,实现类似于CompositionAPI。我们也体会到了她的魅力!以下是Counter的Solid版本示例://Counter.jsximport{createSignal}from"solid-js";exportdefaultfunctionCounter(){const[count,setCount]=createSignal(0);constincrement=()=>{setCount(count()+1);};returnincrement()}>countis{count()};}作为Reacter,你注意到了什么变化?useState()变成了createSignal()count变成了count()这些变化你会学习SolidJS吗?显然不是,写不同的东西没有多大意义。作为新人,你喜欢SolidJS吗?应该不会吧,这段代码看起来不太好理解,而且市面上也没有Solid程序员,直接学React比这还好!临时排行看到这里,我根据个人感觉做一个临时排行老手名单:Vue3=React>Svelte3>Solid老手:别跟我说react,angular,vue,我用jQuery写代码!菜鸟榜:Vue3>Svelte3>React>Solid菜鸟:大佬们最简单的框架是哪个?Vue是国内最招的吗?就是这样!DependencyTrackingBasedParadigm游达曾在直播分享中谈到ReactHooks的一些开发经验问题,比如手动添加依赖、条件语句限制、闭包过期等。无独有偶,各路新锐力量在依赖管理方面大显身手,通过各种手段实现了依赖的自动收集和管理,将开发体验提升了一个档次。SolidJS我们现在向Counter添加一个函数:如果计数发生变化,控制台会打印出来。您可以看到我们不需要手动指定依赖项来跟踪更改。//从“solid-js”导入createEffectimport{createEffect,createSignal};导出默认函数Counter(){const[count,setCount]=createSignal(0);//createEffect用于创建副作用,Solid帮助我们跟踪依赖计数createEffect(()=>{console.log('count:'+count());})constincrement=()=>{setCount(计数()+1);};returnincrement()}>countis{count()};}这里是SolidJS和React的区别,开发者不用再担心依赖问题://一样function,`React`来指定依赖useEffect(()=>{setCount(count+1);},[count])这就是裕达说的React-like语法,实现方式类似于VueCompositionAPI。不要低估这些变化。除了影响开发体验的精神负担外,有时还会不小心写出隐藏的bug。我想这也是国外很多Reacter转用Solid的原因之一。Vue3作为对比,我们把Vue拉出来给大家看import{watchEffect,ref}from'vue'constcount=ref(0)watchEffect(()=>{console.log('count:'+count.友大Onecall总结的其他共同点,符合原生JS直觉,自动跟踪依赖,无需手动声明引用稳定性,无需使用CallbackSvelte3Svelte响应式系统是基于编译的,所以不需要做依赖跟踪,但是作为用户,我们只关心代码怎么写。看看Svelte的写法:letcount=0//sideeffects写在'$:'之后$:console.log(count)constincrement=()=>{count+=1}还是最简洁的一,$将解决问题!对Svelte的喜爱又增加了~临时排名看到这里,我的排名发生了变化:Svelte和Vue在新秀榜上处于同一水平!老手榜:Vue3=React>Svelte3>Solid老手:别跟我说react,angular,vue,我用jQuery写代码!菜鸟榜:Vue3=Svelte3>Solid>React菜鸟:woc太NB,选Svelte!为了尽可能提升基于编译的响应式系统的开发体验,大家使出了大招,开始在编译阶段做文章,比如各种基于编译的响应式解决方案:Svelte、VueReactivityTransform,solidlabelsSvelte的轮子兄弟Harris在Svelte中充分利用了编译时的能力。例如,在下面的代码中,一个简单的$符号可以产生副作用代码letcount=0//当编译器找到`$:`时,它会使用下面的代码作为count$的副作用:console.log(count)constincrement=()=>{count+=1}这看起来真的很NB。作为新手,不需要学习响应机制和相关API,非常简洁。然而,简洁是有代价的。针对这一点,友达大举出击斯维尔特。看看他说的有没有道理:$:语法只能在Svelte组件中使用,组件之外需要一套不同的API。$:只能在顶级范围内使用,不能在函数中使用。SvelteStoresAPI此storesAPI是上文“$:语法只能在Svelte组件中使用”中提到的另一组不同的API。让我们体验一下。比如我们在JS中提到count就是为了让不同的组件共享状态。使用Svelte,我需要这样做:import{writable}from'svelte/store';//usewriteable()tocreateawritablecountexportconstcount=writable(0);我会在Vue中这样做:import{ref}from'vue'exportfunctionuseCount(){//Useref()tocreatearesponsivecountconstcount=ref(0)return{count}}这里Vue实现维护了组件内部书写的一致性,这真的很好。但是,我认为将Svelte作为槽点来喷是没有意义的。Svelte只是推迟了学习API的时间。如果我不学习CompositionAPI,我是写不出这段Vue代码的。另外,如果需要全局状态管理,我还得学一个Vuex语法,这也不能让我学的少。响应式限制的另一个槽点是:$:只能在顶层作用域中使用,不能在函数中使用。我觉得裕达想要的是能够把这个逻辑提炼成一个函数,让这个逻辑可以被复用。例如,使用CompositionAPI,我们可以:计数是${count.value}`);alert(`计数是${count.value}`);})return{count}}但我们不能这样做:functionuseCount(){$:{console.log(`计数是${count}`);alert(`计数是${count}`);}}或:$:useCount()functionuseCount(){console.log(`计数为${count}`);alert(`thecountis${count}`);}这个限制性问题其实就是上面的StoresAPI问题。我们可以使用StoresAPI来完成提取,但是我们失去了$:的一致写法。导出函数useCount(){constcount=writable(0);数数。subscribe(value=>{console.log(`计数为${count}`);alert(`计数为${count}`);});return{count}}在VueReactivityTransformVue3引入Ref后,.value的精神负担一直饱受诟病,游达也想出了很多解决方案。实验性新功能VueReactivityTransform就是其中之一。我们可以这样写代码:letcount=$ref(0)//使用$ref来声明一个响应式对象watchEffect(()=>console.log(count))//你可以不用.valuecount++//你使用时不需要.value相关文件:https://vuejs.org/guide/extras/reactivity-transform.html#refs-vs-reactive-variables这个被小友称为比较通用的方案,不在上述Svelte限制。真的很好用~看来大家还是支持这个方案的,期待转正!在Solid-labels之前,我们看到了solid中reacthooks-likeAPI的使用。个人认为存在以下问题:这套API不符合原生JS的直觉。比如我觉得count是一个值,不应该作为一个函数来调用。也希望在修改的时候直接赋值。另外,总是需要导入solidimport{createEffect,createSignal}from"solid-js"//...createEffect(()=>{//使用时需要加括号:count()console.log('count:'+count());})//修改时需要调用setXX方法setCount(count()+1);使用固体标签怎么样?让我们看一下前面使用solid-labels实现的Counter示例://$signal()创建响应式数据letcount=$signal(0)//$effect()添加副作用,直接调用count$effect(()=>console.log(count))//直接修改countcount++,使用插件实现更简洁直观的语法,无需导入扎实的工具和方法,赞!项目地址:https://github.com/LXSMNSYC/solid-labels暂列可以说大家都在用编译或者翻译来简化API,提升开发体验,而且都非常简洁优雅,而且每一个有自己的特点:VueReactivityTransform和Solid-labels是上下文无关的统一模型。好处是重构和优化,成本是入门的初始成本。Svelte属于上下文受限模型。优点是上手成本低,无需了解响应式实现机制。我认为这场比赛没有赢家,他们都很优秀。所以,我的排名没有变!老手榜:Vue3=React>Svelte3>Solid老手:别跟我说react,angular,vue,我用jQuery写代码!菜鸟榜:Vue3=Svelte3>Solid>React菜鸟:woc太NB了,不知道选什么!基于编译的运行时优化也是如此。通过使用编译时能力,每个人都可以做到极致优化,达到最佳性能!但是这里Svelte和Solid走了一条与Vue3完全不同的路,我们称之为虚拟DOM。你是什??么意思?也就是说,他们都放弃了React开启的流行了10年的虚拟DOM方案,在性能上达到了巅峰!下面就跟着村长一起来看看到底发生了什么吧!不同策略对性能的影响如前所述,Svelte和Solid通过放弃虚拟DOM实现了接近原生DOM的优异性能,尤其是Solid轻松超越Vue3,远超React。连友达都感叹:扎实的表现真的很NB!来看一下我9月21日重新生成的性能统计图:不是说虚拟DOM会带来性能提升吗?这确实是八股面试题的答案,但实际上游达已经在知乎上回答了这个问题。可以阅读原文:网上说操作真实DOM比较慢,但是测试结果比React快。为什么?也就是说,通过使用编译或翻译能力,Svelte和Solid最终都生成了直接操作DOM的更新函数。虽然两者的实现细节不尽相同,但都达到了鱼和熊掌兼得的效果,即提高开发效率,又能保证性能。针对于此,有大推出了一项新作,即所谓的Vapor模式,即用户在以后使用Vue3时可以指定一个组件使用DOM来编译结果,从而提高性能。关于这一点,我认为友达纯粹是靠节奏驱动,增加了使用的复杂度。在大多数情况下,好处并不明显。这里的两款新锐赛车正试图与众不同,吸引用户的眼球。现代Web开发的瓶颈从来不是性能,而是开发效率和可维护性。所以虽然数据看起来不错,但是我觉得这不是一个很大的亮点,所以我们的排名不变!老手榜:Vue3=React>Svelte3>Solid老手:别跟我说react,angular,vue,我用jQuery写代码!菜鸟榜:Vue3=Svelte3>Solid>React菜鸟:woc太NB了,不知道选什么!不同策略对生成代码量的影响最后,我们从最终生成代码量的角度来讨论一下三个框架的性能表现。下图来自有大直播的原图:可以看出,由于Svelte和Solid不需要虚拟DOM相关的运行时代码,所以初期相比Vue存在QQ差距;但是在15个组件的关键节点之后,我们发现Svelte打包体积开始快速攀升,而Solid和Vue增长非常平缓,可以说是并驾齐驱。这里我可以说一下,如果你特别在意执行速度和打包体积,比如一些手机h5页面,看来Solid是你最好的选择。斯维尔特呢?考虑到出色的开发体验和综合性能,只要不是大型项目,应该都能胜任。很抱歉,我没有制作一个包来向您展示结果。主要是我觉得我们的业务代码多几k少几k,在现在的网络情况下是微不足道的!总结到总结的激动时刻,在我看来,这两个框架值得花时间去学习吗?值得!他们的存在一定是有原因的。Svelte和Solid在国外如此火爆也不是没有原因的。他们可以在内敛的前端框架市场杀出一条血路,占据一席之地。相信一定有适合自己的应用场景和优势。