软件开发架构师

InfoQ访谈:前端框架Svelte 3将反应性移入JavaScript语言

前端 31 2019-05-24 15:29

Svelte 前端框架最近发布了Svelte 3。Svelte 3 引入了一种新的方法来声明式地表示用户界面实现中涉及的不变量连接实体。因此,开发人员可能不再需要出于性能的考虑而手动处理重新渲染,或者手动同步相关的状态片段。Svelte 3 有新的 Logo、口号和网站。Sapper(基于 Svelte 类似 Next.js 的应用程序框架) 和Svelte Native(面向移动应用程序开发)正在升级到 Svelte 3。InfoQ 采访了 Svelte 的创建者 Rich Harris,并讨论了 Svelte 3 的意义及其对开发人员的影响。

Svelte 3 是 Svelte 前端框架最新的主要迭代。Rich Harris介绍了 Svelte 3 的目标:

版本 3 是一个重大的变革。在过去的 5 到 6 个月中,我们一直致力于提供出色的开发体验。现在,你编写组件 *所需的样本代码比其他框架都要少很多了

该版本的核心是一种新的语法,用于声明式地表示渲染过程中涉及的变量之间的永久关系。Svelte 3 的文档区分了三种情况:反应性赋值、反应性声明和反应性语句。

为了举例说明反应性赋值,Harris 使用 Svelte 和其他前端框架给出了一个计数器递增的简单例子:

复制代码
// 使用 Svelte
const { count } = this. get();
this. set({
count: count + 1
});
// 使用 React
const { count } = this.state;
this.setState({
count: count + 1
});
// 使用 Vue
(...)
data: () => ({count: 0}),
(...)
this.count += 1;

在这些示例中,开发人员需要捕获或发出嵌入式框架状态更改的信号,以便触发相关的计算和效果。使用 Svelte 3,开发人员只需给变量赋值:

复制代码
count += 1;

Svelte 会在构建时生成相应的同步代码:

复制代码
count += 1; $ $invalidate(' count', count);

反应性声明处理各种变量之间的关系。使用 Svelte 3,开发人员现在可以将变量之间的关系编写为一个等式,使用 Svelte 编译器确保等式右侧变量的更改反映在左侧变量中,就像电子表格中一样。在下面的例子中:

复制代码
<script>
let count = 1;
// 符号`$:`的意思是指当这些值变化时就重新运行
$: doubled = count * 2;
$: quadrupled = doubled * 2;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
Count: {count}
</button>
<p>{count} * 2 = {doubled} </p>
<p>{doubled} * 2 = {quadrupled} </p>

语法 $:double = count * 2; 引入了一个将变量 doubled 与变量 count 连接起来的等式。在这里,Svelte 编译器将生成代码,在 count 更新时更新 doubled:

复制代码
let doubled, quadrupled;
$ $self. $ $.update = ( $ $dirty = { count: 1, doubled: 1 }) => {
if ( $ $dirty.count) { $ $invalidate( 'doubled', doubled = count * 2); }
if ( $ $dirty.doubled) { $ $invalidate( 'quadrupled', quadrupled = doubled * 2); }
};

反应性语句是指每次因变量发生变化时都要进行求值的语句。它们还使用 $ 语法:

复制代码
< script>
let count = 0;
$: if ( count >= 10) {
alert(` count is dangerously high!`);
count = 9;
}
function handleClick() {
count += 1;
}
</ script>
<button on:click={handleClick}>
Clicked { count} { count === 1 ? ' time' : ' times'}
</button>

框架会把它编译成如下代码:

复制代码
$ $self. $ $.update = ( $ $dirty = { count: 1 }) => {
if ( $ $dirty.count) { if (count >= 10) {
alert(`count is dangerously high!`);
$ $invalidate( 'count', count = 9);
} }
};

InfoQ 采访了 Svelte 的创建者 Rich Harris,并讨论了 Svelte 3 背后的动机及其对开发人员的影响。

InfoQ:请给我们介绍下 Svelte 的历史。您是《卫报》使用的另一个基于模板的前端框架 Ractive 的创建者,您为什么还要创建 Svelte?

Rich Harris:Ractive 是 2012-13 年产生的 UI 框架的一种,是那个时代的产物。它功能强大且直观,但与其他同类产品一样,它需要在运行时解释声明式组件代码,这将带来一定的损失。与直接手工编写代码来操作 DOM 相比,你需要使用更大的 JS 包,而且性能更差。

到 2016 年,一切都变了。移动设备,而不是桌面设备,突然占据了大部分流量,这使得包的大小和性能变得更加重要。多亏了 Babel 和 TypeScript 这样的项目,JS 社区重新适应了编译器和构建步骤,所以我就开始想,一个理解声明式组件的编译器能否将它们转换成高度优化的指令代码。到目前为止,我已经花了几年时间考虑 UI 框架设计,并且构建了一个模块打包器(Rollup)和一个编译器(Buble),所以我觉得自己有很好的条件来做尝试。

InfoQ:Svelte 3 引入了一个新的语法来解决一个组件内的同步问题。那么组件间的同步 / 通信呢?假设两个组件读写一个共享的状态片段,或者两个组件必须通信。您如何使用 Svelte 处理可能的同步问题?

Harris: Svelte 有一个名为 store 的原语,它与内置的反应系统一起工作。它是一个非常简单的契约——包中有一个引用实现,但是你也可以封装其他库,比如 Redux 或 xstate——可以任意组合。我们还对 TC39 提出的可观察性规范(由 RxJS 之类的库实现)提供了原生支持,因为它们恰好符合 Svelte store 契约。

InfoQ:是否有可能将一个 Svelte 的组件打包到一个可以在其他框架中使用的 Web 组件中?反过来,在 Svelte 中使用 Web 组件有多容易?

Harris: 编译器的一个好处是可以从相同的组件代码生成不同的输出。生成 Web 组件只需设置一个编译器选项。使用 Web 组件同样简单——Svelte 在Custom Elements Everywhere测试套件上的得分为 30/30。

InfoQ:如果 Svelte 可以编译成 Web 组件,这是否意味着开发人员可以在他们的代码库中逐步引入 Svelte?这可行吗(与现有代码可能存在任何冲突吗,如冲突标记、捆绑问题等等)?

Harris: 是的,Svelte 的设计考虑到了增量采用。自定义元素是实现这一点的一种方便的方法,只要你带来了合适的 polyfill。不过,这取决于“主”框架——例如,React 对自定义元素的支持很差,所以在迁移期间,最好使用一个 React 封装器来封装 Svelte 组件(比如react - svelte)。

InfoQ:开发人员怎么用 Svelte 处理嵌套路由?

Harris: 最简单的方法是使用 Sapper,这是一个构建在 Svelte 组件框架之上的应用程序框架。Sapper 基于应用的文件夹结构为你提供了一个完整的声明式嵌套路由系统,类似于 Next.js,但有许多重要的增强。

对于喜欢基于组件或配置路由的开发人员,有几个社区维护的项目可以供他们选择。

InfoQ:如何测试一个 Svelte 应用程序?

Harris:默认的 Sapper 模板内置了 Cypress 集成。对于单个组件测试,我经常使用 Puppeteer。我们还在研究最常用的测试故事,应该很快就可以拿出来分享了。

InfoQ:请您给出三个采用 Svelte 的理由?

Harris: 首先,你将编写更少的代码,这是加速软件构建和减少 Bug 的最可靠的方法。其次,与主流框架相比,你可以获得更好的性能保证,这意味着,随着应用的增长,或者随着你扩展到设备速度较慢和连接普遍存在的新市场,你不必停下来重写。

第三,Svelte 有许多传统框架认为超出范围的特性。这是因为——作为一个编译器——Svelte 只需要包含你实际使用的特性,而为其他人节省字节。这意味着我们可以自由地包含其他框架团队认为是浪费的东西,比如声明式转换和动画。

InfoQ:三个不使用 Svelte 的理由?

Harris:我们还没有像更成熟的框架那样丰富的编辑器集成和开发工具。我们还没有一流的 TypeScript 支持。我们不属于财大气粗的公司——我们只是一群真正的信徒。

InfoQ:Svelte 下一步有什么计划?

Harris: 呼声最高的特性是 TypeScript 支持,所以我们希望尽快在这方面取得进展。我个人对使用 Svelte 来构建 WebGL 应用程序感到很兴奋,并且我还处于早期的探索阶段。最后,还有一个名为 Svelte Native 的社区项目,它允许你使用 Svelte(由 NativeScript 提供支持)构建 Android 和 iOS 应用程序,并且正在取得一些令人难以置信的进展。

InfoQ:您能举几个使用 Svelte 的公司的例子吗?

Harris: 和其他几家新闻机构一样,我工作的《纽约时报》也将其用于许多项目。我们的网站在主页上还有很多其他的例子——也许最有趣的是,巴西的 Stone 和俄罗斯的 Mustlab 正在使用 Svelte 来驱动嵌入式设备,比如贩卖机系统和智能电视应用。越来越多的前端开发正在转向嵌入式 Web,这些公司意识到,传统的 JavaScript 优先框架不能满足这种环境的需求。

查看英文原文Svelte 3 Front-End Framework Moves Reactivity Into the JavaScript Language, Q&A With Rich Harris

文章评论