作者|冯栓,携程高级前端开发工程师,专注于性能优化、低代码、svelte等领域。一、技术研究近年来,前端框架层出不穷。近两年,前端圈出了一个新宠儿:Svelte。作者是RichHarris,Ractive、Rollup和Buble的作者,前端界的“轮子哥”。通过静态编译减少框架运行时的代码量。编译Svelte组件后,所有必需的运行时代码都包含在其中。除了组件本身,不需要引入所谓的框架运行时!在Github上拥有超过5w颗星!最新的StateofJS2021和StackOverflowSurvey2021排名也在一定程度上反映了它的受欢迎程度。之前的知识里,你是怎么看待svelte这个前端框架的?题下,Vue的作者游雨溪也给了很高的评价:去它的官网看看:官网明确展示了三大特点:少写代码无虚拟DOMT真正的reactive1.1写lesscode顾名思义,就是在Svelte中用最少的代码实现同样的功能。这将在下面的示例中显示。1.2NovirtualDOMSvelte的实现不使用虚拟DOM。要知道Vue和React的实现都是用的虚拟DOM,虚拟DOM不是一直很高效吗?VirtualDOM不是总是高效的吗?其实,VirtualDOM高效是一种误解。VirtualDOM效率高的原因之一是它不直接操作原生DOM节点,因为这会消耗大量的性能。当组件状态改变时,它会使用一些diff算法计算出本次数据更新的真实视图变化,然后只改变需要改变的DOM节点。用过React的同学可能会发现React并没有想象中的那么高效,框架有时会做很多无用的工作,体现在很多组件会“无缘无故”地重新渲染。所谓重新渲染就是重新执行你定义的类Component的render方法,或者重新执行你的组件函数。组件重新渲染是因为VitualDOM的效率是基于diff算法,如果存在diff,则必须重新渲染组件才能知道组件的新状态和旧状态是否发生了变化,所以至于计算哪个DOM需要更新。正是因为框架本身很难避免无用渲染,所以React允许你使用一些API比如shouldComponentUpdate、PureComponent、useMemo来告诉框架哪些组件不需要重新渲染,但是这也引入了很多模板代码。那么如何解决VirtualDOM算法效率低下的问题呢?最有效的解决方案是不使用VirtualDOM!1.3真正的响应式第三点是真正的响应式。上面也提到了前端框架要解决的首要问题是:当数据发生变化时,相应的DOM节点会被更新。这是反应性的。我们先看看Vue和React是如何实现响应式的。ReactReactive通过useState定义倒计时变量,在useEffect中通过setInterval每秒递减一次,然后在视图中同步更新。这种实现背后的原理是什么?React开发者使用JSX语法编写代码,JSX会被编译成ReactElement,运行时会生成一个抽象的VirtualDOM。然后每次重新渲染render时,React都会重新对比前后两个VirtualDOM,如果不需要update则什么都不做;如果只是HTML属性发生变化,会通过调用节点的setAttribute方法反映到DOM节点上;如果DOMtype发生变化、key发生变化或在新的VirtualDOM中找不到,则会执行相应的删除/添加DOM操作。Vuereactive实现了与Vue相同的功能。Vue背后是如何实现响应式的呢?大致流程是在编译时收集依赖,基于Proxy(3.x),defineProperty(2.x)getters,setters来在数据变化时通知Watcher。Vue和React等响应式方法存在哪些问题?diff机制给runtime带来了负担。开发者需要优化性能useMemouseCallbackReact.memo...那么Svelte是如何实现响应式的呢?Sveltereactive作为一个框架,其实需要解决的是当数据发生变化时,相应的DOM节点会更新(reactive)的问题。VirtualDOM需要比较新旧组件的状态来达到这个目的,而一个更高效的方法其实就是当数据发生变化时,直接更新对应的DOM节点。这就是Svelte所采用的方法。Svelte会在代码编译时将每次状态变化转化为DOM节点对应的操作,从而在组件状态变化时快速高效地更新DOM节点。深入理解后,发现它采用了Compiler-as-framework的概念,将框架的概念放在编译时而不是运行时。当你写的应用代码用Webpack或Rollup等工具打包后,会直接转化成JavaScript对DOM节点的原生操作,这样bundle.js就不会包含框架的runtime。那么Svelte能减少多少包大小呢?以下是RealWorld项目的统计数据:从上图可以看出,Svelte的bundlesize是Vue的1/4,React的1/20!单从这个数据来看,Svelte的框架确实对bundlesize做了很大的优化。看到如此强大的数据支撑,不得不说真的动心了!2、项目落地为了验证Svelte在营销h5的可能性,我们选择了口罩机项目:上图为口罩机项目的设计稿。不难看出,核心逻辑并不是很复杂,这也是我们选择它作为Svelte尝试的原因。首先,项目的基础设施是基于svelte-webpack-starter创建的,它集成了TypeScript、SCSS、Babel和Webpack5。不过这个基础模板只提供了简单的支持,比如项目中用到的一些图片和字体,需要loader单独处理。启动项目,熟悉的helloworld:先看看这里的核心。当然,在开发环境中使用webpack有时候不得不说体验不是很好。每次都需要几秒钟。我们改用Vite,基本上秒启动:Vite的配置也比较简单:2.1组件结构的区别与React组件不同,Svelte代码更像是我们以前写HTML、CSS和JavaScript的时候(这个很类似于Vue)。所有JavaScript代码都位于Svelte文件顶部的标记中。然后是HTML代码,也可以在标签中写样式代码。组件中的样式代码只对当前组件有效。这意味着为组件中的
