ð - 实时聊天和游戏应用程序和无服务器网络网
在这篇Sveltekit帖子中,我们谈论在您的Sveltekit应用程序中添加实时事件。我最近一直在尝试各种以事件为导向的建筑解决方案,并且对产品着迷。 Webhooks和Rest钩是我在此空间中最熟悉的协议。虽然,酒吧和网站插款可能更为普遍。
Websocket
WebSockets启用双向,状态连接。 HTTP连接通常涉及一个请求文档的客户端,并且服务器对其进行了响应,以 request-revense 模式。对于实时聊天或游戏,客户将需要将消息或移动发送到服务器。同样,服务器将需要将这些收到的更新推向其他参与者客户;也就是说,没有客户单独请求它们。客户可以通过HTTP反复ping,检查更新,尽管开放的Websocket可以提高效率。
如果您使用实时重新加载或热装加载的前端工具,则可能已经在运行WebSockets服务!在这里,浏览器将向DEV服务器打开Websocket,通常,当输入文件更改时,服务器关闭该连接,客户端将其作为信号来刷新页面。
。即时的
我们知道为什么WebSocket与实时聊天和游戏相关,但是实时是什么?通常,当我们在这里谈论实时时,我们需要延迟(数据在客户端和服务器之间传递的时间)低于100毫秒。对于快速节奏的动作游戏玩家将以低于20 ms的速度目标,尽管对于聊天和我们的小策略游戏,但较慢的东西是可以忍受的。
合理:无服务器网站
明显的平台提供了无服务的Websocket;将实时聊天或多人游戏游戏添加到您的Sveltekit应用程序中的理想选择。尽管您可以在传统服务器上的节点上运行Sveltekit应用程序,但无服务器模式当前很常见,并且非常适合Sveltekit。您可能熟悉的替代方案是 PartyKit , pubnub 和 pusher 。就我个人而言,我只尝试过了很大的尝试。如果您尝试过其他人,请在下面放置评论。
我们在这篇文章中查看一个简单的Sveltekit策略游戏。我曾经在长途旅行中玩游戏,尽管有两只不同的彩色笔和一块纸!我们使用的是,无论您有一个更复杂的游戏还是实时聊天,基本设置都不会太不同。
ð§±我们正在构建的
我创建了巨大的游戏,以此来尝试出色的无服务器Websocket产品。它基于广场经典游戏。在Svelte社区中,有一种传统,可以将Svâ固定在任何应用程序名称的开始。除了Svoast,SvHighlight和Sveriodic Table以外,别无其他。别无选择,只能致电游戏sqvuasieð。
我们将在本文中从头到尾构建游戏,我们将专注于亮点,或者我应该说svhighlightsð。
ð¶服务器端适当设置
有一个JavaScript SDK,它将与Svelte一起使用。首先将此ably
软件包添加到您的项目:
pnpm add -D ably
Sveltekit明显的服务器代码
i基于我的项目基于Ably Labs project, which uses older SvelteKit APIs。
import { ABLY_API_KEY } from '$env/static/private';
import { Temporal } from '@js-temporal/polyfill';
import { error as svelteKitError, fail, redirect } from '@sveltejs/kit';
import Ably from 'ably';
import type { Actions, PageServerLoad } from './$types';
import type { Types } from 'ably';
let ably: Types.RealtimePromise = new Ably.Realtime.Promise(ABLY_API_KEY);
export const actions: Actions = {
play: async ({ cookies, request }) => {
const form = await request.formData();
const name = form.get('name');
clientId = crypto.randomUUID();
// TRUNCATED...
// player name stored to cookie
cookies.set('session', JSON.stringify({ clientId, name }), {
path: '/',
expires: new Date(Temporal.Now.plainDateTimeISO().add({ hours: 2 }).toString()),
sameSite: 'lax',
httpOnly: true
});
throw redirect(303, '/');
}
};
export const load: PageServerLoad = async function load({ cookies, url }) {
try {
const session = cookies.get('session');
if (session) {
const { clientId, name } = JSON.parse(session);
const token = await ably.auth.requestToken({ clientId });
return { name, token };
}
} catch (error: unknown) {
const { pathname } = url;
const message = `Error in server load function for ${pathname}: ${error as string}`;
throw svelteKitError(500, message);
}
};
我将此逻辑保留在+page.server
而不是+page.ts
上,因为我们要避免与客户端共享API密钥。最重要的是,游戏有一个小的服务器端状态,将玩家分配给游戏会议。
请注意,该软件包具有完整的打字稿支持,我们将Types
导入为从ably
导入。
actions
块包含用于记录用户中的逻辑。如果您是Sveltekit表单的新手,请查看最近的SvelteKit Forms post where we explore the APIs building a grammar checking app。在这里,我们使用前端表单获取播放器名称并将此信息与新的Sveltekit会话相关联。在初始化Websocket之前提供了这些数据,我们将会话数据存储在仅HTTP的cookie中。然后,我们将用户浏览器重定向到成功表单上的/
路线。这将涉及页面加载函数,现在可以访问新的用户相关会话数据。
Sveltekit恰当:加载功能
一旦用户填写表单,加载功能就最有用,并且我们有一个Sveltekit会话。我们在文件顶部初始化了ably
:
const ably = new Ably.Realtime.Promise(ABLY_API_KEY);
现在,在加载函数中,我们为用户创建一个新的Aut auth令牌:
const token = await ably.auth.requestToken({ clientId });
return { token };
到目前为止,这是所有服务器端。 WebSocket连接开始了他们的生命,以常规的HTTP连接开始,然后将其升级。遵循常规的HTTP请求响应模式,我们将从浏览器初始化此HTTP连接。因此,这里最重要的部分是将令牌传递给浏览器,从而使其启动了连接。从负载功能返回token
使其可作为Prop客户端可用。
我在此处提取了很多与游戏相关的细节,并且有一个链接,更深层。
。𧧽客户端设置
通常,我更喜欢使用SVELTE操作进行组件相关的设置。但是,在这里,onMount
方法似乎更自然。渴望看看您是否有一种干净的方式在Svelte Action中进行此设置!
onMount
代码在渲染页面后运行。例如,如果您是setting up a chart,则可能会遇到它。您将具有图表所绘制的DOM元素。通常,您使用JavaScript代码执行该绘图任务。不过,您不能在其存在之前绘制到DOM元素!将绘图代码放在onMount
函数中是确保您避免这种情况的一种方法,因为仅在DOM渲染后才调用该功能。
<script lang="ts">
import app from '$lib/configuration';
import type { Types } from 'ably';
import { Realtime } from 'ably';
import { onMount } from 'svelte';
import type { PageData } from './$types';
export let data: PageData;
let { name, token } = data ?? {};
const { ablyChannelName } = app;
let channel: Types.RealtimeChannelPromise | null = null;
$: serviceStatus = channel ? 'Connected to Ably' : 'Offline';
onMount(async () => {
const ably = new Realtime.Promise({
...token,
authCallback: () => {
/* add token refresh logic */
}
});
await ably.connection.once('connected');
channel = ably.channels.get(ablyChannelName);
channel?.subscribe(({ name: messageName, data: messageData }) => {
if (messageName === 'turn') {
/* logic for processing message */
}
});
});
</script>
- 在
9
中,我们可以访问我们从服务器加载函数导出的明智的代币。 - 我们为Line
13
中的 ably通道创建一个变量。频道将应用程序消息与我们拥有的其他应用程序隔离。另外,对于多玩家实时游戏,您可能会有单独的大厅和游戏中的聊天。每个人都可以拥有自己的频道。 - 我们使用令牌生成的服务器端来创建
17
的onMount
中的Websocket。
连接升级到WebSocket
开始连接过程后,我们只等待连接完成。在引擎盖下,HTTP连接将升级到Websocket。拉开浏览器开发人员工具和跟踪网络请求。您应该看到常规的http 200获取请求,然后一个101切换协议获取请求,在其中可以为您升级连接!
!作为最后一步,客户需要订阅频道。请注意,我们在28
-32
行中具有回调函数。此回调详细介绍了我们在Websocket上收到新消息时想发生的事情。对于聊天应用程序,您需要渲染该消息供用户阅读。对于Sqvuable Game,该消息将是对手移动的更新。
这些消息可以具有任意形状以适合您的应用程序。这是来自Sqvualy的示例消息:
{
"messageName": "turn",
"messageData": {
"player": "player1",
"vertical": false,
"row": 0,
"column": 0
}
}
也是将消息发送到频道中的一个示例:
<script lang="ts">
export let channel: Types.RealtimeChannelPromise | null;
channel.publish('turn', {
player,
vertical: false,
row: rowIndex,
column: columnIndex
});
</script>
关于游戏的设计和巧妙的实现
游戏仅依赖于JavaScript和HTML元素。每个网格线都是HTML按钮。我使用CSS将它们放在正确的位置,并将其转换为正确的颜色。有较小的组件可以代表水平和垂直线,以及将所有的网格行组合成网格组件。按钮具有描述性文本,可访问性。
鉴于结构,您可能最终会使用大量的道具钻探。为了最小化,我使用Svelte商店来维持哪个玩家的转弯状态,以及是否已经要求网格线,如果是的话,则是谁。然后,组件可以从所需的状态中撤出,避免道具钻探。
通常,在游戏中,在涵盖了所有线条之前,有一点继续演奏没有意义。那是因为两个玩家都不能宣称任何新的广场。 Svelte商店有助于简化达到此状态时锻炼的逻辑。
ðsveltekit恰当:扩展
我只是真正地划过了表面上的本身可以做的事情,以及如何将其与事件驱动的体系结构集成在一起。我对扩展有一些想法,很高兴您能与您的联系:在下面的评论中,或者您更喜欢。
最明显的缺失作品是续签代币。这些游戏应该很短,因此这不是早期的优先事项,尽管我将考虑设置它,因此我可以将逻辑提取到我从事的其他更复杂的应用程序中。
-
明显的存在:Presence offers an alternative method of communication在通道上。例如,您可以自动发送vonda刚刚在聊天中输入了房间样式状态更新。
-
Upstash redis :这是handy service which offers serverless Redis。 Redis对于存储排行榜将是很棒的,这可能会给最多产的球员带来启示。免责声明:我过去曾做过为Upstash的作品。
-
kafka :Apache Kafka是一个实时活动的活动商店。我们可能会使用它来存储对隐私友好的玩家统计数据,例如平均获胜时间。可以定期对这些数据进行分析,以更新在Redis Upstash Redis中缓存的领导者董事会和其他统计数据。 UpStash提供serverless Kafka和Confluent is another alternative。
ðð½Sveltekitabally:总结
在这篇文章中,我们大量了解了您如何设置实时Sveltekit Ably应用程序。特别是,我们看到了:
- Websockets 是什么,以及为什么要考虑使用它们
- 无服务器的实时可以节省您的时间构建实时应用
- 如何在Sveltekit App中进行合理设置
请see the full repo code on the Rodney Lab GitHub repo。我希望您发现这篇文章有用,并且可以将代码用作您自己的实时应用程序的起点。最近,我一直在研究以clickhouse进行分析的工具以及尝试进行尝试的工具。您是否想查看有关我在这些主题上学习的内容的更多内容?您是否有好奇的服务或工具,希望看到一些内容?在下面放置评论或reach out on other channels。
ðð½Sveltekit恰当:反馈
如果您发现此帖子有用,请参见下面的链接以获取本网站上的更多相关内容。我希望您从视频中学到了一件新事物。让我知道是否有任何方法可以改进它。我希望您能在自己的项目中使用代码或入门器。请务必在Twitter上分享您的作品,给我提及,以便我可以看到您的工作。最后,请务必让我知道您想看的其他简短视频的想法。请继续阅读以找到与之联系的方法,以下更远。如果您发现此帖子很有用,即使您只能负担得起,请consider supporting me through Buy me a Coffee。
。最后,请随时在社交媒体帐户上分享所有发现有用的关注者的帖子。除了在下面发表评论外,您还可以通过@askRodney on Twitter and also askRodney on Telegram与联系。另外,请参见further ways to get in touch with Rodney Lab。我定期发布在SvelteKit以及Search Engine Optimization上,以及其他主题。另外,subscribe to the newsletter to keep up-to-date带有我们的最新项目。