Transcript

00:00:00大家好!欢迎来到新一期的 Basel 社区会议。
00:00:29我是 Maya Avendano,是 Basel 的开发者体验工程师。
00:00:32如果这是您第一次参加我们的会议且看不到聊天框,
00:00:35欢迎加入我们的社区平台 [community.basel.com/live](https://www.google.com/search?q=https://community.basel.com/live)。
00:00:41在那里您可以使用聊天功能,也非常鼓励大家提出问题。
00:00:45如果您是在 X 或其他平台观看,也可以在那些平台上互动。
00:00:49我非常期待今天的会议,因为告诉大家一个小秘密,
00:00:53我曾做了好几年的 Svelte 开发者,还用 Svelte 做过很多业余项目。
00:00:58所以我也是铁杆粉丝,甚至还有它的文化衫。
00:01:01那么,对于各位 Svelte 粉丝和感兴趣的朋友们,
00:01:06我们今天邀请到了 Svelte 团队的一些成员。欢迎大家。
00:01:12嗨。大家好!你们想向大家介绍一下自己吗?
00:01:21好的,我是 Rich。
00:01:24我研究 Svelte 已经 10 年了,因为我是 2016 年开始这个项目的。
00:01:32最初,我是为了在我的记者日常工作中使用它,做视觉新闻,
00:01:38用 JavaScript 来辅助新闻叙事。接着在四年多前,
00:01:44我加入了 Basel,这成了我的全职工作,并一直做到现在。
00:01:53是的,我想没人能像你一样坚持这么多年。
00:01:57我想我有大概五年的 Svelte 维护经验。
00:02:02我叫 Simon。我也在 Basel 工作,负责 Svelte 项目,
00:02:08我是通过前公司的一次黑客松接触到 Svelte 的。
00:02:13当时我想尝试点新鲜的东西。那时候我主要用 Angular。
00:02:18在黑客松用了 Svelte 后,我立刻就爱上了它,但也知道,
00:02:22“好吧,我日常工作里没法用这个,那我还能怎么保持联系呢?”
00:02:29我知道这听起来很极客。就这样,我成了一名兼职维护者。
00:02:34几年后,我有机会加入 Basel 全职从事这项工作。
00:02:39是的,一直干得很开心。
00:02:43我是 Elliot。就像我偶尔提醒 Rich 的那样,
00:02:46他开始做 Svelte 那年,我刚好高中毕业。
00:02:49所以我参与维护的时间还没那么长。
00:02:54但我是在 2021 年底或 2022 年初开始的。
00:02:59大概是在 SvelteKit 测试版期间,我发现并加入了 Svelte 社区。
00:03:04然后在 Rich 加入后不久,我也入职了 Vercel。
00:03:09如果我没记错的话,应该是同年秋天。
00:03:12但我当时负责很多其他的东西,比如 Vercel 的官网。
00:03:16令人惊讶的是,一年多以前,感觉并没过多久,
00:03:23我成功转到了 Svelte 团队。从那时起我就一直在全职做这个。
00:03:27最近比较酷的事情是,我正在为 Svelte 编写异步 SSR(服务端渲染)的实现。
00:03:36这类纯粹的极客软件开发工作正是我热爱的,
00:03:43也是我一直以来喜欢 Svelte 的原因。
00:03:48太棒了。很高兴你们都能来。
00:03:51对于观众中可能不太熟悉的朋友,你们能简要解释一下 Svelte 和 SvelteKit 吗?
00:04:00当然可以。Svelte 包含很多含义。
00:04:04它是一个社区,是一种生活方式,但它也是一个声明式组件框架。
00:04:11如果你用过 React 或 Vue 之类的工具,就会熟悉其基本概念,
00:04:15即与其去写“document.createElement”和“setAttribute”这些繁琐的操作,
00:04:21不如用声明式组件来描述你的应用。
00:04:25然后框架的任务就是提取这些声明式意图,并将其转化为屏幕上的实际内容。
00:04:33Svelte 与那些框架略有不同,它采用了“编译优先”的设计。
00:04:40本质上,它是一种被转化为高性能原生 JavaScript 的语言。
00:04:48在使用上,它与很多其他框架非常相似,但由于其设计,
00:04:53我们能以比某些框架更优雅、更精简的方式来做事。
00:04:58除了作为底层基础的 Svelte 之外,
00:05:02我们还有一个建立在 Svelte 之上的框架叫做 SvelteKit,
00:05:08如果你熟悉 React 的世界,它有点像我们的 Next.js。
00:05:13它增加了其他所有功能:路由、服务端渲染、数据加载和构建工具,
00:05:18以及构建应用所需的所有功能,让你不必
00:05:24费心去自己动手构建这些基础设置。
00:05:28太棒了,非常感谢。
00:05:29我知道你们最近一直在后台紧锣密鼓地筹备。
00:05:32我很想知道你们过去几个月都在忙些什么。
00:05:37我听说你们还准备了一些演示?
00:05:41我们确实有一些演示。
00:05:43我想我先开始可以吗?
00:05:44因为从逻辑顺序来看,先谈谈异步 Svelte 的开发会比较合适,
00:05:51然后我们再聊聊基于此构建的其他东西。
00:05:55听起来不错。
00:05:55好的,在过去一年多时间里,我也记不太清具体多久了。
00:06:02我们一直在开发被我们简称为“异步 Svelte”的东西,也许我分享一下屏幕,
00:06:12我可以演示一下它是什么,然后我们再看看异步 Svelte 的一些用途。
00:06:20我得回想一下分享屏幕的按钮在哪。
00:06:26得点过所有的权限对话框。
00:06:28请稍等。
00:06:30分享整个屏幕。
00:06:33好了。
00:06:34好的,我想我正在分享屏幕了。
00:06:35我是在分享屏幕吗,还是仍在后台?
00:06:38是的,我们看到了。
00:06:40好的,对于还没接触过的朋友,这是 Svelte.dev。
00:06:43这是我们的官网。
00:06:44这是演练场,你可以在这里尝试 Svelte 而无需安装任何东西,
00:06:49也不用去折腾命令行。
00:06:51你可以直接在这里写代码。
00:06:53这是默认看到的演练场页面。
00:06:55也许我把它调大一点,好让大家都能看清。
00:06:58这里我们有一些状态。
00:07:03这些有趣的东西,我们称之为“runes”。
00:07:05这是你用来声明 Svelte 组件中某些内容会发生变化的方式,
00:07:10并且当它改变时,我们需要进行重新渲染。
00:07:12所以我们有一个姓名(name)和一个计数器(count)。
00:07:15然后我们在上方显示这个姓名。
00:07:17接着我们将它的值绑定到这里的内容上。
00:07:21我们可以这样做。
00:07:24我们可以点击这个按钮,数值就会增加。
00:07:27这些都是非常基础的操作,几乎每个框架
00:07:29都能以某种方式实现。
00:07:35而异步 Svelte 增加的是直接在组件内部
00:07:41使用 Await 关键字的能力。
00:07:45比如——我们先删掉姓名和这些东西。
00:07:49让我们把这个变成 ID,并从 1 开始。
00:07:56我要做的是从外部源
00:08:01提取一些 JSON 数据。
00:08:04首先,我将创建一个由 ID 派生出的东西。
00:08:10所以每当 ID 改变时,这个 URL 就会被重新计算。
00:08:16你可以看到如果我在这里输入 URL,随着数值改变,
00:08:22URL 也会跟着改变。
00:08:24然后我将使用那个 URL 获取一些数据,
00:08:28my data 等于 derived。
00:08:30在这里面,我可以写 Await fetch URL。
00:08:36然后我们要获取响应并将其转换为 JSON。
00:08:41我相信只要是做开发的,这类代码
00:08:43肯定都看过无数遍了。
00:08:47然后在这里,我们创建一个块引用(block quote)
00:09:00并展示我们从这里提取的数据。
00:09:03你可以看到,如果我们看一下——
00:09:06坏掉了。
00:09:13这就是我们要获取的内容,我们希望能显示它。
00:09:16所以在这里,我要写 data.quote。
00:09:21噢,出错了。
00:09:23Simon, Elliott,如果你们看出我哪里写错了,请告诉我。
00:09:28噢,不,只是延迟问题。
00:09:30好的。
00:09:31然后在下面,我们加上名言的作者。
00:09:40也许我们在写代码的时候可以先把那个延迟去掉。
00:09:44我也不知道。
00:09:46如果我把它包在花括号里会有帮助。
00:09:50现在如果我点击这个,它会消失,
00:09:55然后获取新数据并渲染出来。
00:09:58这听起来可能非常基础且琐碎,
00:10:01但如果你看看在几乎所有其他框架中
00:10:08该如何实现这一点,你会发现它很快就变得极其复杂。
00:10:10你必须有一些本地状态,然后
00:10:13必须有一个副作用(effect),可能是 useEffect
00:10:16或在其他框架中的等效功能,在里面执行 fetch。
00:10:20当 fetch 完成时,你再赋值给本地状态,
00:10:25而且你还得处理错误等一堆事情。
00:10:27这真的会变得相当复杂。
00:10:32但有了这个,它就很自然地工作了。
00:10:36如果有延迟——
00:10:43它依然能正常工作。
00:10:45尽管你可能会看这个并想:等等,
00:10:46如果我连续点击按钮多次,
00:10:49我其实只想跳转到最终结果。
00:10:51我不想处理中间的那些加载过程。
00:10:53我们也可以做到这一点。
00:10:54我们可以在这里说,如果我导入这个助手函数
00:10:58叫 get abort signal from self,然后把 signal 传给 fetch,
00:11:11那么这一次,当我点击按钮时,
00:11:15它实际上会丢弃所有中间的请求,
00:11:19并直接跳转到最后一个,
00:11:21因为之前的那些请求响应得太晚了。
00:11:26到那时,我们已经再次更改了 ID。
00:11:28所以我们要取消现有的信号。
00:11:33好了,我们还能做什么?
00:11:34嗯,也许我想看到这个按钮立即更新。
00:11:38所以我们可以用 state.eager 来跳出
00:11:43异步阻塞状态。
00:11:47这也挺有用的。
00:11:49我们还可以加些样式。
00:11:51我们可以说 data loading 等于 effect.pending
00:11:58大于 0。
00:11:59然后如果我们处于加载状态,
00:12:04我们可以在加载东西的时候让它淡出。
00:12:11再次强调,所有这些事情如果你
00:12:13尝试自己去协调,
00:12:15将会非常困难。
00:12:17我们甚至可以做得更进一步。
00:12:19假设我想在名言后面加张照片。
00:12:28它可能看起来像这样。
00:12:37如果我改变它,我会得到
00:12:41一堆不同的照片。
00:12:42显然全是笔记本电脑,我也不知道为什么。
00:12:46好,这张照片漂亮点。
00:12:48不过,你会注意到这里
00:12:50有一点延迟。
00:12:52我们先得到名言数据,然后图像才蹦出来。
00:12:57因为我们在渲染图像,
00:12:58然后必须回到网络去
00:12:59获取图像,这体验不太好。
00:13:02所以如果我们把它替换成一个小型的预加载(preload)
00:13:07助手函数,我将从我的 utils 模块导入它,
00:13:17那么这一次,我们会看到图像和名言
00:13:24会同时出现。
00:13:27我刚刚发现了一个小 bug。
00:13:28我们得去修复它。
00:13:30但你应该明白了。
00:13:31我们可以在计算中使用 await,
00:13:34也可以在模板中使用它。
00:13:36所有这些东西都能够完美地协作,
00:13:40并支持多个组件
00:13:44在响应同一事件时独立工作。
00:13:47它还支持服务端渲染。
00:13:49它能做到所有这些事情,如果你
00:13:52在没有异步 Svelte 的情况下处理
00:13:55会非常痛苦。
00:13:58有了这个基础,我们就能构建
00:14:02一些非常酷的东西,接下来我将把它交给
00:14:05另外两位来介绍。
00:14:09好的。
00:14:10我来快速演示一下远程函数(remote functions),它是
00:14:17它将建立在此基础之上。
00:14:19现在我们在 Svelte 中有了异步功能,这非常强大。
00:14:24但 SvelteKit,作为它之上的元框架,
00:14:27可以说仍然处于“旧世界”。
00:14:30我们有这些 load 函数,它们存在于不同的文件中。
00:14:34因此,我们无法真正利用刚才看到的
00:14:38所有这些炫酷的新特性。
00:14:41所以我们现在正在开发的是远程函数(remote functions)。
00:14:45它们已经可以在 SvelteKit 中使用了。
00:14:48虽然还是实验性的,但你现在就可以尝试。
00:14:50为了节省时间,我将展示
00:14:55使用远程函数最简单的方法。
00:14:59我要做的是,
00:15:01创建一个非常简单的计数器,
00:15:04每当我点击按钮时,它就会增加计数,
00:15:08但这个计数将保存在服务器上。
00:15:10我将在 counter.remote.ts 文件中实现它。
00:15:16我先从一个 count 变量开始。
00:15:18然后写一个 get count。
00:15:20接着我们将使用来自 $app/server 的查询。
00:15:26这是一个远程查询。
00:15:29我们在这里直接返回 count。
00:15:31在另一端,我们就可以使用它,
00:15:37写成 await get count,并从刚才的文件中导入。
00:15:44这个导入看起来就像普通的 TypeScript 导入。
00:15:48只是我们导入的是一个函数,
00:15:52当我们调用它时,它会返回一个 promise。
00:15:54所以我们需要使用 await。
00:15:56但实际上,这已经跨越了客户端和服务器的边界。
00:16:01这个 get count 实际上是在服务器上运行的。
00:16:05实际发生的过程是,客户端
00:16:08向一个隐藏的端点发送请求,
00:16:14并从中返回数据。
00:16:17当然,它也支持服务端渲染。
00:16:19所以在初始加载时,它不会向后端发送请求,
00:16:23而是直接执行。
00:16:25现在我们有了这个计数,但还不能对它
00:16:29做任何操作。
00:16:29我们想要增加它。
00:16:31所以这将是另一个远程函数。
00:16:34我们将快速实现它——不用 copilot。
00:16:38这个命令不对。
00:16:40我们需要来自 $app/server 的 command。
00:16:45在这里,我们只需要更新服务器状态。
00:16:49但这本身还没有帮助,
00:16:52因为作为一个 command,我们还需要告诉它
00:16:55同时发送一个更新。
00:16:58所以我们在这里调用远程函数 get count,
00:17:03并在其上调用 refresh。
00:17:05通过这种方式,我们基本上是在告诉它,
00:17:08执行一个“单次往返”的变更。
00:17:10当你被调用时,将计数加一,
00:17:14然后向客户端发回信息,
00:17:19告知每当在此页面使用 get count 时,
00:17:22现在应该已经增加了一,
00:17:24因为已经有了新的可用状态。
00:17:27所以如果我现在把这个加进去,
00:17:29我要做一个 on click 操作来增加计数。
00:17:37这就是我要做的全部。
00:17:38它看起来就像一个普通的函数调用。
00:17:40但重申一下,这实际上调用了服务器。
00:17:43现在当我点击这个按钮,我就增加了计数。
00:17:49以上就是对远程函数的
00:17:53一次非常简略的初步展示。
00:17:55你可以用它构建更多东西。
00:17:58它与 AI 结合得也非常完美。
00:18:01比如,就在会议开始前五分钟,
00:18:06我问这个代码助手(code copilot):嘿,帮我
00:18:12构建一个《传送门》主题的基础博客,
00:18:18我想展示一些远程函数。
00:18:20你应该使用 Svelte 5 和 MCP,即 Svelte MCP。
00:18:25Elliot 稍后会谈到这一点。
00:18:29使用那个工具,再加上远程函数和异步功能。
00:18:32它基本上一次性就完成了。这是预渲染的。
00:18:34这个块是预渲染的。
00:18:35我可以现在在这里输入——
00:18:37保存一下。
00:18:42然后它就更新了。
00:18:43在底层,它的工作原理基本相同。
00:18:49我们来快速浏览一下,
00:18:53我们使用了 await get posts。
00:18:56get posts 是一个预渲染函数,
00:18:59这意味着它是在构建时执行的,
00:19:01而不是在运行时。
00:19:05我们在下面还有一个评论区,
00:19:06我们在那里加载评论,并使用一个表单
00:19:12来发布新评论等等。
00:19:15这些全部都使用了远程函数,
00:19:19没用到任何 load 函数。
00:19:23而且 AI 一次性就写好了。
00:19:24我想 Elliot 接下来会
00:19:27更详细地谈谈这部分内容。
00:19:32是的,听起来很棒。
00:19:34我也得像 Rich Harris 那样,
00:19:37做一下开头时那种屏幕共享的操作。
00:19:41好的,这就行了。
00:19:46我要花一分钟跟各位谈谈
00:19:52我们最近一直在做的 AI 开发工作。
00:19:57说到“我们”,我想明确一点,那并不包括我。
00:19:59我主要是指一个叫 Paolo 的人,还有
00:20:02Svelte 的其他一些贡献者。
00:20:06实际上,我们最近完成的大多数 AI 相关工作
00:20:09都出自他们之手。
00:20:13所以非常感谢他们。
00:20:14他们的工作非常出色。
00:20:15好的,让我在这里放大一下。
00:20:18完成了。
00:20:24我可以花很长时间来讲解
00:20:27我们为了实现这些目标而构建的东西,
00:20:28因为我们有一个 MCP 服务器。
00:20:31它有一些非常酷的功能。
00:20:32我们还发布了一些“技能”(skills)。
00:20:36但值得庆幸的是,你其实
00:20:38不需要详细了解所有这些工作原理,
00:20:41因为我们还发布了 Open Code 和 Cloud Code 插件。
00:20:43我要在这里安装 Open Code 插件,
00:20:47这基本上就是复制这段配置,
00:20:48然后把它放入你库中的
00:20:52Open Code.json 文件里。
00:20:55然后我要让 Open Code 帮我建立一个网站。
00:20:58我们来看看效果如何。
00:21:00我要问它。
00:21:06我在 assets 中提供了一些图片。
00:21:10遗憾的是,我也得把这个放大一下。
00:21:11不走运,看起来我没法把它放大。
00:21:17好了。
00:21:28好的。
00:21:34[正在输入]
00:21:34我们来看看会发生什么。
00:22:00不要出错。
00:22:06没错,这非常重要。
00:22:09如果你不在提示词末尾加上这一句,
00:22:11效果就不会那么好。
00:22:12当它运行的时候,我可以给你们
00:22:13介绍一下他们一直在做的事情。
00:22:15如果你来到 Svelte 网站
00:22:18并查看我们的 AI 文档,就能看到整体概况。
00:22:21我们发布了一个 MCP,它有自己的 CLI 工具。
00:22:25它还有一些——
00:22:28噢,嘿,他在过去五分钟内修复了这个问题。
00:22:32所以现在看起来和五分钟前不一样了。
00:22:36但我们在你的机器上启用了几个工具。
00:22:40其中大多数——
00:22:43或者说前两个工具的作用是获取关于 Svelte 的准确信息。
00:22:46它教会你的智能体如何阅读文档,
00:22:51而且是专门以一种
00:22:53能找到特定信息的方式去阅读,
00:22:58而不用倾倒整个文档
00:22:58或者四处乱逛,从而浪费
00:23:03时间和上下文窗口。
00:23:05还有一个非常棒的 Svelte 自动修复器,
00:23:08他们构建这个是为了识别那些
00:23:11大模型常犯但效果不佳的模式,并进行修复。
00:23:12它还集成了一些游乐场(playground)功能,
00:23:15你可以在这里直接使用。
00:23:17另一件很酷的事情是,
00:23:21当我们审视所有这些 AI 相关的东西时,
00:23:26我们的核心设计决策之一是
00:23:33如何让它对智能体和人类都有用?
00:23:37我们不希望这是一个不透明的东西,
00:23:39让你的智能体莫名其妙地知道一些事情,
00:23:44而你却不知道,而且很难弄明白。
00:23:46所以基本上我们所做的每一件事,
00:23:52都尝试将其集成到文档中。
00:23:55因此我们发布的这些“技能”,
00:23:59无论你安装的是 Open Code 还是 Cloud Code 插件,
00:24:00它们实际上
00:24:01也会把所有的内容发布到文档里。
00:24:04所以你大可放心,如果你想知道
00:24:07我们告诉了你的大模型哪些最佳实践,
00:24:09你可以自己过来阅读。
00:24:12它们会一直像这样显示在我们的网站上。
00:24:15现在让我们回去看看这个东西
00:24:18运行得怎么样了。
00:24:20目前还没有太多进展。
00:24:25也可能已经做了很多。
00:24:27是的,我们做了很多样式处理。
00:24:31我想我得打开我的本地主机
00:24:34看看它到底完成了什么。
00:24:35什么都没有。
00:24:39好吧,我不想在这个东西
00:24:45还在思考整个过程的时候耽误大家时间。
00:24:56它可能需要一段时间。
00:25:00所以如果我们最后还有时间,可以再回来
00:25:03看看大模型为我们的手工土豆大炮生意
00:25:07想出了什么主意。
00:25:10是的,这就是我们过去几个月
00:25:12所做的 AI 开发工作。
00:25:13太棒了。
00:25:15是的,在新时代这非常重要。
00:25:19我真的很想知道接下来会发生什么。
00:25:20你们对什么充满期待?
00:25:25下一个版本将是 SvelteKit 3。
00:25:26目前正在积极开发中。
00:25:32但它不会是一个包含
00:25:37大量新功能的巨型版本。
00:25:40它基本上是一个弃用
00:25:46大量旧东西的机会,清理掉一些累赘,
00:25:51以便我们可以构建所有令人兴奋的新特性。
00:25:53最大的变化是它将使用 Environment API。
00:25:56会有大量的新功能。
00:25:57这基本上是一个弃用
00:25:59许多旧功能的机会,算是清理战场,
00:26:02以便我们能够构建所有令人兴奋的新内容。
00:26:06最大的变化是它将使用环境
00:26:09API,因为 Vite 6 在两小时前刚刚发布。
00:26:15而且它将要求使用 Svelte 5 作为最低版本。
00:26:21所以你依然可以继续使用 Svelte 4。
00:26:25在那之后,我们将专注于
00:26:29使异步 Svelte 变得稳定,并使远程函数稳定。
00:26:33听起来不错。
00:26:37我听到小道消息说,我
00:26:41要把话筒转交给 Elliot,因为大语言模型
00:26:44一直在后台运行。
00:26:46你想给我们展示一下成果吗?
00:26:47不出所料,它决定在我们
00:26:49切换到下一个环节后的那一毫秒刚好完成。
00:26:55那我们来看看这里。
00:26:59是的,这就是我们的手工土豆大炮商店页面,
00:27:03刚才大概用了价值 1 美元的 token 生成的。
00:27:07实际上,粗略浏览一下代码,
00:27:13它做得非常好,没有写出任何疯狂的代码,
00:27:17而且使用了我认为是 Svelte 的最佳实践。
00:27:22所以大家可以试试看。
00:27:25让我们知道你们是否喜欢。
00:27:27我对 Paolo 和其他人
00:27:29在这些 AI 功能上所做的工作印象非常深刻。
00:27:33我们希望不断改进。
00:27:35所以请随时向我们提供反馈。
00:27:38谢谢。
00:27:40太棒了,看来今天演示之神站在我们这一边。
00:27:45我们要不要开始提问环节?
00:27:47我想聊天框里已经有一些问题了。
00:27:51我来开个头吧。
00:27:53有一个关于远程函数(Remote Functions)的问题。
00:27:57远程函数会支持流式传输(streaming)吗?
00:28:00远程函数的开发者体验(DX)太棒了。
00:28:03想在任何地方都用到它。
00:28:05是的,我想 Richard 可以回答这个问题,
00:28:06因为你正负责那个领域。
00:28:10是的,真巧你提到了这个。
00:28:12因为我目前正在开发的一个应用
00:28:15非常需要这个功能。
00:28:17我们——Simon 前阵子提交了一个 PR,
00:28:22实现了一部分功能。
00:28:23此后,我们对设计方案
00:28:28有了进一步的演进。
00:28:31但这是我们非常急于着手处理的事情。
00:28:35所以,如果我们在一个星期后做这个直播,
00:28:40我们可能就能说:"看,这是合并请求。"
00:28:43虽然现在还没到那一步,
00:28:44但请放心,它的优先级非常高。
00:28:47我们对这个功能感到非常兴奋。
00:28:49对于那些不熟悉的人,基本上
00:28:51我们要聊的是实现查询函数的一个实时版本,
00:28:55当你从服务器请求
00:28:59数据时,它会返回一个异步迭代器,
00:29:04每当有新数据时,
00:29:09它就会将数据推送回客户端。
00:29:12这样你就能获得实时数据,而不需要任何轮询
00:29:15或者类似的操作。
00:29:16一旦页面不再显示该数据,
00:29:21请求就会关闭。
00:29:23异步迭代器会自动进行清理。
00:29:26这是一种非常优雅的思考方式,
00:29:28用来处理这些实时问题。
00:29:31是的,非常期待。
00:29:33为了完全说清楚,我想
00:29:35告诉大家,Rich 所说的 "很快就会处理" 是指
00:29:38Elliot 目前正挡着我,让我没法做这件事。
00:29:40我正等着他完成某项工作。
00:29:41所以,只要我完成了手头的工作,
00:29:43我们马上就会投入其中。
00:29:45非常好。
00:29:46不错。
00:29:50我们还有另一个问题。
00:29:52那就是,为什么要选择 Svelte 而不是其他框架?
00:29:55显然,我们认为它是最优秀、最强大的框架。
00:30:07但在当今时代,选择任何框架的
00:30:11真正原因应该是
00:30:13说实话,是因为你比其他框架更喜欢它。
00:30:18很大程度上,这更多是关于个人喜好,
00:30:20而不是其他任何因素。
00:30:22尤其是现在,当
00:30:24在框架之间切换变得非常容易时,
00:30:28你手头还有一个神奇的 "向导"(AI)可以教你——
00:30:32"我习惯在 Vue 里用这种方式做。"
00:30:35"在 Angular 或其他框架里该怎么做?"
00:30:37AI 可以做到这一点。
00:30:38在当今时代,学习曲线基本上
00:30:43已经被拉平了。
00:30:45所以你应该使用那个让你生产力最高、
00:30:49且让你用得最开心的工具。
00:30:53这其中一部分是关于项目周边的社区。
00:30:57一部分是关于项目的整体哲学。
00:31:02但我认为在当今时代,你不需要
00:31:05仅仅基于框架 "能做什么" 来做决定。
00:31:11因为它们都能做同样的事情,
00:31:13也不需要纠结哪个框架拥有最大的生态系统。
00:31:16因为那已经不再是问题了。
00:31:18所以,选一个最有趣的框架就好。
00:31:21而我们显然认为那就是 Svelte。
00:31:26非常精彩的回答。
00:31:27太赞了。
00:31:29接下来的问题是:关于缓存(cache)有什么新内容吗?
00:31:35是的,我想这可能是关于远程函数的。
00:31:38在远程函数的背景下,
00:31:41我们目前还没有任何缓存 API。
00:31:45内部有一个提案。
00:31:48这还在计划中。
00:31:51但在其他繁忙的工作中,它被暂时搁置了。
00:31:55但它很快就会被重新拾起。
00:31:58然后我们将拥有一个非常棒的缓存 API,
00:32:01它可以与远程函数完美集成。
00:32:05太棒了。
00:32:06我们有一个轻松点的问题。
00:32:08你心目中理想的 Svelte Summit 举办地在哪里?
00:32:10噢,哇。
00:32:13你们想现场轮流说一下吗?
00:32:16Elliot,你静音了。
00:32:22我的意思是,如果我们讨论的是 "Summit"(峰会/山峰),
00:32:24那我们有珠穆朗玛峰,K2。
00:32:28不,对我来说,地点其实没那么重要。
00:32:34因为我主要是想去
00:32:36和其他 Svelte 开发者叙叙旧。
00:32:38虽然听起来有点俗气,但几乎任何地方都很棒。
00:32:43不过欧洲真的很酷。
00:32:46那边的任何地方
00:32:48都是我还没去过且想去的地方。
00:32:51所以我总是很乐意找个借口去海外走走。
00:32:56Svelte 世界有一种倾向,
00:33:01就是喜欢在所有东西前面加 SV 前缀。
00:33:04无论你想构建
00:33:06什么库或概念,
00:33:08你就在它前面加个 SV。
00:33:11我想如果我们真的贯彻这一点,
00:33:12那么我们的会议应该在 Svalbard(斯瓦尔巴群岛)举行。
00:33:15不错。
00:33:20那是——一个挪威群岛。
00:33:23你是刚才当场搜的吗?
00:33:27其实是前几天聊天时刚提到的。
00:33:31是的,挺偶然的。
00:33:35是的。
00:33:38所以,如果让我完全放开想象,我想我梦想的地点
00:33:41其实是在一艘船上。
00:33:45就在大海上。
00:33:47天气晴朗。
00:33:49然后在船上待个三天。
00:33:52那肯定很酷。
00:33:55以上这些听起来都很棒。
00:33:57我也非常期待下一届 Svelte Summit 的到来。
00:34:00说到社区和活动,
00:34:03我们有一个问题:人们该如何
00:34:05参与到 Svelte 中来,有什么活动或社区
00:34:07机会吗?
00:34:11各种活动一直都在进行中。
00:34:13如果你去 sveltesociety.dev,
00:34:15你可以看到活动日历。
00:34:16那里还有很多关于如何参与的最佳方式
00:34:19的资源,特别是如果你的地区
00:34:22还没有相关组织,而你有兴趣创办
00:34:25一个 Svelte Society 的分会,那么 sveltesociety.dev
00:34:28就是获取信息的地方。
00:34:33是的,另外如果你是新手,可以加入 Discord,
00:34:36在各个频道里打个招呼。
00:34:41还有针对各个分会或
00:34:47特定语言的专用频道。
00:34:49大多数情况下,它们会链接到
00:34:55其他相应语言的 Discord 频道。
00:34:57例如,还有一个德国 Svelte Society 的 Discord
00:35:00频道。
00:35:01所以,只要进入频道和 Discord 频道,
00:35:06你就可以从那里开始探索。
00:35:08除此之外,Svelte 相关的频道
00:35:12也是个闲聊的好地方。
00:35:16是的,Svelte 的小伙伴们人都非常好。
00:35:18所以,去看看吧。
00:35:22我们还有另一个关于 AI 的问题。
00:35:24Elliot,我知道你谈过这个。
00:35:26有人问,很高兴看到框架开始适应
00:35:29智能体/AI 世界。
00:35:31我想知道你们是否有关于智能体(agents)默认使用 Svelte 的统计数据。
00:35:36不,并没有。
00:35:37我们或许能通过像 v0 这样的工具
00:35:44获得一些类似
00:35:46遥测数据的信号。
00:35:49但总的来说,Svelte——
00:35:53我想说的是 Svelte——负责 Svelte 开发的人们
00:35:57对于收集遥测数据
00:36:01一直持有相对消极的态度。
00:36:06所以,我们拥有的唯一数据
00:36:08就是那些公开可用的。
00:36:10我们可以查看 NPM 的下载趋势,
00:36:14虽然由于某些奇怪的原因,这些数据现在涨得很疯狂。
00:36:18所以可能不要把它们当成金科玉律。
00:36:20是的,别担心。
00:36:22但是,出于隐私原因,我们真的不收集
00:36:25任何关于用户的数据。
00:36:27我们不想在你们的机器上做这种事。
00:36:30所以我们得到的数据都是公开可见的,
00:36:35或许还能从 Vercel 的一些渠道获取一些有用的信息。
00:36:43从轶闻趣事来看,如果你问大语言模型该选什么,
00:36:46什么框架最好,Svelte 经常被提及。
00:36:51所以,至少这一点挺不错的。
00:36:53但如果你不在提示词中明确指定,
00:36:56这是否能转化为用户最终选择 Svelte,又是另一回事了。
00:37:01是的,这非常有趣。
00:37:03一旦你引导它们思考什么是理想的工具,
00:37:06它们通常会说 Svelte。
00:37:08但如果你不说“我想要你用这个框架”
00:37:11或者“我想要你用最好的框架”,
00:37:12只是说“帮我建个应用”,它们通常会默认使用 React。
00:37:17对此我们也没有太多办法去改变。
00:37:21所以我们一直把注意力集中在
00:37:23确保对于那些选择了 Svelte 的团队,
00:37:27能让他们获得尽可能最好的体验。
00:37:29并且让 AI 智能体拥有最强大的能力
00:37:31去查阅文档并查出错误。
00:37:36是的,正如那个传送门主题的博客和 Potato Cannon 网站所展示的,
00:37:42它们在处理上下文
00:37:46以及 MCP 等方面已经变得非常出色。
00:37:50所以,现在你可以非常快速地取得很大进展。
00:37:56太棒了。
00:37:57是的,很高兴看到你们在这方面所做的一切努力,
00:37:58同时也兼顾了
00:38:01人类和 AI 智能体这两类受众。
00:38:04我们还有几个关于 Svelte 功能的
00:38:06具体问题。
00:38:08其中一个是,在标记(markup)中多次调用
00:38:11同一个远程函数是否可以,
00:38:14还是我们应该在 script 标签中只保留一个引用?
00:38:17是的,没问题。
00:38:20你现在正负责这一块,所以你来回答吧。
00:38:24目前阻碍 Rich 开发实时查询(live queries)功能的因素,
00:38:26其实就和这个问题有关。
00:38:29是的,多次调用同一个远程函数
00:38:35并在不同地方多次引用它
00:38:39是完全没问题的。
00:38:41当你使用远程函数时,
00:38:44你对查询的心智模型应该是:
00:38:46当我带参数调用一个查询时,
00:38:50我获得的是对该查询的引用,
00:38:54而查询本身与数据是不同的。
00:38:57所以,如果我在应用的任何地方调用 ID 为 1 的 getUser,
00:39:04我实际上在所有地方
00:39:07获得的都是该查询的同一个实例。
00:39:08因此,你对查询的调用会在整个应用中进行去重,
00:39:11这样每组参数最多只会产生一次调用。
00:39:16所以,不同的参数会产生不同的结果。
00:39:19相同的参数会产生相同的查询。
00:39:21它们在整个应用中是去重的。
00:39:24目前还有一些奇怪的限制,
00:39:28这就是我过去几周
00:39:33一直在努力修复、规范化
00:39:37并使其更清晰的工作。
00:39:39希望很快就能发布。
00:39:41但简单来说,答案是肯定的。
00:39:44随处调用并根据需要使用即可。
00:39:47是的,再补充一点,
00:39:48我们之所以在 await 关键字等方面
00:39:51投入这么多精力,
00:39:54是因为我们希望你能够尽可能地
00:39:57在该组件内部表达出
00:39:59它所需要的一切。
00:40:00所以,那种在顶层获取数据,
00:40:04然后小心翼翼地传递给所有需要的子组件的日子,
00:40:08就要结束了。
00:40:10但作为这其中的一部分,如果你必须持有一个查询的引用
00:40:14然后再到处传递,
00:40:15那我们其实还没达到目的。
00:40:17所以我们的想法是,如果这个组件需要一些数据,
00:40:20而那个组件恰好也需要同样的数据,
00:40:22它们之间不需要相互通信。
00:40:24它们只需通过查询接口
00:40:28向系统请求数据即可。
00:40:29系统会负责确保
00:40:32这只会产生一个请求,
00:40:34并且不会在这两个组件之间
00:40:36导致数据不一致。
00:40:40太棒了,谢谢。
00:40:42接下来的问题关于动画和过渡 API。
00:40:47有计划对其进行彻底改革吗?
00:40:49提问者说:我发现通过 attachments
00:40:54传递 flip 的起始/终止尺寸非常麻烦。
00:40:57我简直迫不及待地想处理这个问题了。
00:41:02我已经期待很久了。
00:41:04要做的事情太多了。
00:41:06是的,其他事情总是忙不过来。
00:41:09基本上,当我们设计 attachments API 时,
00:41:12正是考虑到了这一点。
00:41:16过渡和动画非常棒。
00:41:19它们以一种非常简便的方式
00:41:21集成到了框架中,可以轻松实现某些功能。
00:41:25但一旦你超过了某个阈值,
00:41:28它们就心有余而力不足了。
00:41:29你需要对它们进行更多的程序化控制。
00:41:33这就是为什么需要一个程序化 API
00:41:36来定义过渡和动画。
00:41:42而 attachments API——
00:41:46我们的设想是,未来 attachments API
00:41:49可以结合另一个 API,用来指令:
00:41:52“嘿,当我从 DOM 中被移除时,
00:41:54先等一下,让我做个淡出
00:41:58或者扭动之类的动作。”
00:42:00然后再把我从 DOM 中移除。
00:42:02这将能够实现
00:42:06一些更高级的过渡动画场景。
00:42:09但我们还没走到那一步。
00:42:11这在计划中。
00:42:12它一定会实现的。
00:42:13但我无法给你一个明确的时间表。
00:42:16肯定不会是在未来的两三个月内。
00:42:22好。
00:42:22至少它已经在考虑范围之内了。
00:42:24听到这个消息很开心。
00:42:25酷。
00:42:25我想我们还有时间回答最后一个问题。
00:42:27最后一个。
00:42:29Svelte 是数据库无关的,但团队成员们
00:42:32最喜欢的数据库是什么?
00:42:34再来一轮快速问答。
00:42:37SQLite。
00:42:37我过去在做快速实验时用过 Neon,
00:42:47感觉非常棒。
00:42:50是的,SQLite 很好。
00:42:53我真正期待的是看到这些同步引擎
00:42:59变得非常出色且普及,这样我们
00:43:02就能实现“本地优先”(local-first)的应用了。
00:43:05到时候——老实说,我并不在乎
00:43:09后台用的是什么数据库,这是我的简短回答。
00:43:13是的,我认为——
00:43:15我不确定我是否真的有一个最喜欢的,因为——
00:43:18当你问“你最喜欢的数据库是什么”时,
00:43:22答案有很多种,因为不同的数据库
00:43:24擅长不同的领域。
00:43:26所以你真的必须知道
00:43:28你为什么要选择某个数据库,才能选出一个心头好。
00:43:31我觉得像 Convex 这种对于“本地优先”
00:43:36同步引擎非常有意思。
00:43:38我觉得它们很酷,有很多很棒的特性。
00:43:41但我最喜欢的通用数据库
00:43:42其实是 Dynamo。
00:43:45虽然上手可能有点让人抓狂,
00:43:47但它真的非常快。
00:43:49而且它的扩展性极其出色。
00:43:51但我真的很喜欢 SQL。
00:43:55所以,如果一个项目能用 SQL 数据库解决,
00:43:58我大概率会选它,因为我的职业生涯
00:44:04是从数据分析之类的开始的。
00:44:07所以 SQL 基本上是伴随我成长的。
00:44:09所以,我不确定我是否有一个唯一的最爱,
00:44:14但我就是这么考虑的。
00:44:16不错。
00:44:20我们这里有一条 Paolo 的留言。
00:44:20我知道你刚才提到了他。
00:44:23他说:“我看到了太多的颜色。”
00:44:24“我们确定 Rich、Simon 和 Elliot 真的在 Vercel 工作吗?”
00:44:27“我的椅子可是黑色的。”
00:44:32是的,Paolo 一直在催我穿 Vercel 的连帽衫,
00:44:35但这里太热了。
00:44:38好了,伙计们。
00:44:40但我把它放在衣柜里了,
00:44:45天冷的时候我就会穿上它。
00:44:48这就是我们想听到的,展示周边文化。
00:44:51太棒了。
00:44:54是的,我非常期待 Svelte 的未来,
00:44:55也非常感谢各位能加入我们,
00:44:58感谢你们在幕后付出的所有努力。
00:45:01同时也非常感谢 Svelte 团队的其他成员,
00:45:03那些虽然没在直播现场但辛勤付出的维护者们。
00:45:05还要向精彩的 Svelte 社区致意。
00:45:09是的,感谢 Rich、Simon、Elliot 今天加入我们。
00:45:11谢谢。
00:45:16再见。
00:45:17非常荣幸。
00:45:18好了,观众朋友们请先不要走,
00:45:20在结束之前,我们还有一位非常特别的嘉宾。
00:45:23我们邀请到了来自 Vercel 教育团队的 Eve。
00:45:26你好。
00:45:31最近怎么样?
00:45:32你好,Eve。
00:45:33很好。
00:45:33你呢?
00:45:34我很好。
00:45:35谢谢。
00:45:36这真是一支全明星级别的团队。
00:45:36是的。
00:45:40真是一种享受。
00:45:41好的。
00:45:44你想向我们介绍一下 Academy
00:45:45以及你们最近在忙些什么吗?
00:45:47是的,我很乐意。
00:45:49如果你还没听说,Vercel 现在有了 Academy(学院)。
00:45:50我们已经上线了 11 门课程。
00:45:55其中最新的一门就在今天上线了,
00:45:57那就是——锵锵——Svelte on Vercel 课程。
00:46:03团队在帮助课程最终完工方面
00:46:10给予了很大的支持。
00:46:13在课程中,我们会构建一个滑雪提醒应用。
00:46:15所以如果你是一个滑雪者——
00:46:18噢,是的。
00:46:23我正准备分屏显示,现在把它投出来。
00:46:25太棒了。
00:46:28来了。
00:46:29来了。
00:46:30这样看起来更令人兴奋。
00:46:31Svelte on Vercel 课程现已上线。
00:46:34在课程中,你将构建一个滑雪提醒应用。
00:46:36在当今世界,如果你今年是个滑雪者,
00:46:40你会知道今年的雪季有点艰难。
00:46:43降雪量极低。
00:46:47各地气温都很高。
00:46:48所以,当你被告知什么时候是个滑雪的好日子时,
00:46:50这非常重要。
00:46:52这就是我们在课程中构建的
00:46:54用来实现这一目标的应用。
00:46:58我们可以设置各种——你可以针对
00:46:59你寻找的各种条件编写不同的提醒,
00:47:02这样当适合滑雪的日子到来时,你就能在那儿,
00:47:06而不会浪费掉可能的滑雪天。
00:47:10是的,课程涵盖了 Svelte。
00:47:13如何在 Vercel 上部署?
00:47:17如何使用 AI SDK?
00:47:19如何使用 Workflows?
00:47:21以及一路上的一些生产环境小贴士。
00:47:23太棒了。
00:47:27精彩。
00:47:28我坚信在实践中学习。
00:47:29是的,这太棒了。
00:47:31非常感谢。
00:47:33我们也会在直播资源中
00:47:34加入课程链接。
00:47:36Eve,感谢你今天加入我们。
00:47:38太棒了。
00:47:41非常感谢。
00:47:41好的。
00:47:42我们的直播环节到此结束了。
00:47:46非常感谢社区成员们
00:47:49陪伴我们度过这段时光。
00:47:51不瞒你说,今天的聊天室非常热闹。
00:47:52看到这一点真的很棒。
00:47:54希望你们喜欢这次内容。
00:47:56套用 Rich Harris 的话:Svelte 是一种生活方式。
00:47:58所以,去尝试一下吧。
00:48:02去构建更多 Svelte 的东西。
00:48:03如果你想参加未来的社区活动,
00:48:05你可以在我们的社区平台上找到所有详情,
00:48:08网址是 [community.vercel.com/live](https://community.vercel.com/live)。
00:48:11谢谢大家。
00:48:13回头见。
00:48:15拜拜。
00:48:16再见。

Key Takeaway

本次 Vercel 社区会议重点展示了 Svelte 5 的异步编程模型、SvelteKit 的远程函数演进以及深度集成 AI 的开发者工具生态。

Highlights

Svelte 引入了「异步 Svelte」特性,允许直接在组件中使用 Await 关键字处理异步逻辑。

SvelteKit 推出了实验性的「远程函数 (Remote Functions)」,简化了跨客户端与服务器边界的数据处理。

Svelte 团队发布了 MCP 服务器和 AI 插件,旨在提升 AI 智能体编写 Svelte 代码的准确性与效率。

SvelteKit 3 正在开发中,将以 Svelte 5 为最低版本要求并集成 Vite 6 的环境 API。

Vercel Academy 上线了全新的「Svelte on Vercel」课程,通过实战项目教授 Svelte 与 AI SDK 的集成。

远程函数未来将支持流式传输 (Streaming),通过异步迭代器实现无需轮询的实时数据推送。

Timeline

会议开场与嘉宾介绍

主持人 Maya Avendano 欢迎社区成员参加 Basel(即 Vercel)社区会议,并表达了自己作为 Svelte 长期粉丝的兴奋之情。随后,Svelte 创始人 Rich Harris 以及核心维护者 Simon 和 Elliot 依次介绍了自己的背景。Rich 分享了 Svelte 自 2016 年诞生至今的十年历程,Simon 讲述了从 Angular 转向 Svelte 的职业转变。Elliot 则提到自己从负责 Vercel 官网到全职加入 Svelte 团队的心路历程。这一部分建立了会议的专业基调,并强调了核心团队对项目的长期承诺。

Svelte 与 SvelteKit 核心概念定义

Rich Harris 为观众简要定义了 Svelte 作为一个声明式组件框架的核心哲学。他解释说,Svelte 采用「编译优先」的设计,将代码转化为高性能的原生 JavaScript,而非在运行时处理。相比 React 或 Vue,Svelte 的语法更加优雅且精简,能减少开发者编写繁琐操作的需求。接着,他介绍了 SvelteKit 作为元框架的角色,将其类比为 Svelte 世界的 Next.js。SvelteKit 提供了路由、服务端渲染 (SSR) 和数据加载等全套构建应用所需的功能。

异步 Svelte 现场演示:Await 关键字的威力

Rich 进行了「异步 Svelte」的实战演示,展示了如何在 Svelte 5 的 Runes 模式下直接在组件内使用 Await。通过获取 JSON 名言数据的例子,他对比了传统框架中需要 useEffect 和本地状态的复杂实现,而 Svelte 仅需几行代码即可完成。演示涵盖了派生状态 (derived)、中止信号 (abort signal) 的处理以及异步加载时的 UI 淡出效果。此外,他还展示了如何通过预加载助手函数解决图像加载延迟的问题。这一特性极大地简化了数据获取的逻辑,并原生支持服务端渲染。

SvelteKit 远程函数 (Remote Functions) 详解

Simon 接力展示了 SvelteKit 正在开发的「远程函数」特性,这是一种跨越客户端和服务器边界的新型数据交互方式。他现场编写了一个计数器,展示了如何通过简单的 TypeScript 导入在前端调用服务器端的查询和命令。远程函数支持自动去重和单次往返的变更刷新,使开发者无需手动维护 API 路由或隐藏端点。他还展示了一个由 AI 协助生成的博客案例,证明了远程函数在简化架构方面的潜力。目前的远程函数虽处于实验阶段,但已展现出极高的开发体验优化。

AI 集成:MCP 服务器与开发者插件

Elliot 详细介绍了 Svelte 团队在 AI 工具链上的投入,包括新发布的 MCP 服务器和 Open Code 插件。这些工具的核心设计目标是让 AI 智能体能够准确阅读 Svelte 文档,并识别模型常犯的错误模式。他现场演示了 AI 智能体如何在短时间内生成一个完整的「土豆大炮商店」网页,且代码符合最佳实践。团队强调,所有提供给 AI 的「技能」和知识都会同步发布在官方文档中,确保透明度。这种做法旨在同时服务于人类开发者和日益增多的 AI 编程助手。

SvelteKit 3 展望与未来路线图

团队讨论了即将到来的 SvelteKit 3,该版本将作为清理旧有弃用功能的契机,并全面拥抱 Vite 6 的环境 API。Rich 明确表示,SvelteKit 3 将要求最低使用 Svelte 5,以确保生态系统能够利用最新的异步特性。关于未来的功能,团队确认正在积极开发远程函数的流式传输支持,利用异步迭代器实现实时数据推送。针对「为何选择 Svelte」的问题,Rich 认为在框架能力趋同的今天,个人喜好和开发乐趣是核心理由。他还开玩笑地提议未来的 Svelte 峰会可以在斯瓦尔巴群岛或海上游轮举行。

社区互动 Q&A 与 Vercel Academy 课程发布

在问答环节,团队回答了关于远程函数重复调用(会自动去重)以及动画过渡 API 改革计划等具体技术问题。尽管暂无明确的动画重构时间表,但团队确认 attachments API 将是未来的核心。随后,来自 Vercel 教育团队的 Eve 宣布了「Svelte on Vercel」官方课程正式上线。该课程通过构建滑雪提醒应用的实战项目,涵盖了 AI SDK、Workflows 和部署技巧。最后,主持人总结了会议,引用 Rich Harris 的话称 Svelte 是一种「生活方式」,鼓励社区成员积极尝试。

Community Posts

View all posts