实时仪表板在各种应用程序中都非常有用,从跟踪网站分析到监控实时财务数据,甚至密切关注物联网设备。
?在本教程中,我们将向您展示如何使用 React 和 Encore.ts 构建一个。您将学习创建一个可即时传输更新的动态仪表板,使您能够做出快速、明智的决策。
要了解我们将构建的内容,请在此处查看成品的 GIF 和源代码。让我们深入了解一下!
在我们开始之前,请确保您的计算机上安装了这些东西
Encore.ts 是一个开源框架,可帮助您使用 TypeScript 构建后端,确保类型安全。它轻量且快速,因为它没有任何 NPM 依赖项。
在开发分布式后端系统时,往往很难在本地复制生产环境,导致开发者体验不佳。您最终可能会处理很多复杂性,只是为了让事情以合理的方式在本地运行,这需要时间来专注于构建实际的应用程序。 Encore.ts 通过提供用于构建分布式系统的完整工具集来解决这个问题,包括:
好的,我们讨论了 Encore 是什么以及它如何帮助我们构建后端服务。在下一节中,我们将在本地安装 Encore 并开始构建。
要使用 Encore,我们需要安装 CLI,这使得创建和管理本地环境变得非常容易。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
创建 Encore 应用程序非常简单,只需运行命令即可。
encore app create
您将被问到以下问题,因此请相应地选择您的答案。
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
应用程序创建后,您可以在 encore.app 中验证应用程序配置
{ "id": "real-time-dashboard-<random-id>", "lang": "typescript" }
好的,我们已经创建了 Encore 应用程序。我们下一节讨论 Encore 中的 Streaming API。
在讨论流式 API 之前,我们先讨论一下 Encore 中的 API。在 Encore 中创建 API 端点非常容易,因为它提供了 encore.dev/api 模块中的 api 函数来定义类型安全的 API 端点。 Encore 还内置了对传入请求的验证。 API 的核心是具有请求和响应架构结构的简单异步函数。 Encore 会在编译时解析代码并生成样板,因此您只需专注于定义 API。
流 API 是允许您向应用程序发送数据和从应用程序接收数据的 API,从而允许双向通信。
Encore 提供三种类型的流,每种流用于不同的数据流方向:
当您连接到流式 API 端点时,客户端和服务器使用 HTTP 请求执行握手。如果服务器接受此请求,则会为客户端和 API 处理程序创建一个流。这个流实际上是一个允许发送和接收消息的 WebSocket。
好吧,现在我们知道了 Encore 中的 API 和 Streaming API,让我们在下一节中使用 Streaming API 端点创建仪表板服务来实时存储和检索数据。
让我们创建一个仪表板服务,我们将在其中定义销售 API 以将数据传入和传出我们的销售仪表板。
在根级别创建一个名为dashboard的文件夹,然后添加一个 encore.service.ts 文件。此文件将告诉 Encore 将仪表板文件夹及其子文件夹视为服务的一部分。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
然后将以下代码添加到 encore.service.ts 文件中。我们从 encore.dev/service 导入 Service 类,并使用“dashboard”作为服务名称创建它的实例。
encore app create
现在让我们创建一个仪表板.ts 文件并设置销售 API。
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
在设置API之前,我们首先设置数据库来存储销售数据。我们将使用 encore.dev/storage/sqldb 模块中的 SQLDatabase 来创建 Encore 支持的 PostgreSQL 数据库。
我们需要将 SQL 定义为迁移,当我们执行命令 encore run 时,Encore 将拾取该迁移。
在仪表板文件夹中创建一个名为migrations的文件夹,然后创建一个名为1_first_migration.up.sql的文件。确保遵循命名约定,以 number_ 开头并以 up.sql 结尾。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
在这里,我们创建一个名为 sales 的表,包含四列:
接下来,将以下代码添加到dashboard.ts 文件中。
encore app create
在这里,我们创建一个 SQLDatabase 实例,将其命名为仪表板并指定迁移文件夹的路径。
我们正在使用 postgres 包来监听并通知数据库中的更改。
?
接下来,添加这些类型和内存中的映射来保存连接的流(websocket 连接)。
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
接下来,让我们设置一个销售流端点,以便在发生新销售时发送更新。
{ "id": "real-time-dashboard-<random-id>", "lang": "typescript" }
这里我们使用 api.streamOut 函数来定义 API,它接受两个参数:
我们在connectedStreams映射中保持连接,并使用Postgres客户端监听new_sale通道。当新的销售发生时,我们会将更新发送到所有连接的流。
接下来,我们将定义添加销售 API 端点,我们从请求正文中获取销售数据,并使用数据库实例插入新的销售记录。
# create dashboard folder mkdir dashboard # switch to dashboard folder cd dashboard # create encore.service.ts file inside dashboard folder touch encore.service.ts
在这里,将新的销售记录添加到数据库后,我们使用 Postgres 客户端向 new_sale 通道发送包含销售数据的通知。这样,new_sale 通道侦听器就会收到通知并可以采取行动。
最后,让我们设置 API 端点以返回销售记录列表。
import { Service } from 'encore.dev/service'; export default new Service('dashboard');
这里,我们使用db实例方法查询来获取数据,然后处理它以列表的形式返回。
太好了,我们现在已经定义了所有 API 端点。让我们在下一节中探索 Encore 开发仪表板。
我们有带有数据库设置的 API 端点,但是我们如何测试和调试服务呢?不用担心,因为 Encore 提供了本地开发仪表板,可以让开发人员的生活更轻松并提高生产力。
它包含多种功能来帮助您设计、开发和调试应用程序:
当您更改应用程序时,所有这些功能都会实时更新。
要访问仪表板,请使用 encore run 启动 Encore 应用程序,它会自动打开。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
这就是仪表板的外观,您可以在投入生产之前在本地测试所有内容。这使得测试微服务架构变得更加容易,而无需外部工具。
以下是使用 API 浏览器添加新销售的示例。当您单击“调用 API”按钮时,您将收到响应和日志。右侧可以看到请求的痕迹。
单击跟踪链接时,您将获得数据库查询、响应和日志等详细信息。
好了,这就是本地开发仪表板的全部内容。您可以探索其他选项,例如服务目录、流程等。在下一节中,我们将生成具有 TypeScript 类型安全性的客户端,以在前端服务(React 应用程序)中使用,以与仪表板服务 API 进行通信。
Encore 可以使用 TypeScript 或 JavaScript 生成前端请求客户端,保持请求/响应类型同步并帮助您无需手动操作即可调用 API。
在根目录下创建一个名为 frontend 的文件夹,然后运行以下命令使用 Vite 设置 React 项目。
encore app create
接下来,在 src 目录中创建一个 lib 文件夹,添加一个名为 client.ts 的新文件,并将其留空。
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
然后,在 package.json 文件中添加一个名为 gen-client 的新脚本。
{ "id": "real-time-dashboard-<random-id>", "lang": "typescript" }
接下来,运行脚本在 src/lib/client.ts 中创建客户端。
# create dashboard folder mkdir dashboard # switch to dashboard folder cd dashboard # create encore.service.ts file inside dashboard folder touch encore.service.ts
src/lib/client.ts 文件应包含生成的代码。
import { Service } from 'encore.dev/service'; export default new Service('dashboard');
接下来,在lib目录中创建一个名为getRequestClient.ts的文件并添加以下代码。这将根据环境返回 Client 实例。
# make sure you are in dashboard folder touch dashboard.ts
好了,现在我们有了可以在 React 应用程序中使用的客户端来调用仪表板 API。在下一节中,我们将创建前端服务并为实时销售仪表板构建 UI。
在上一节中,我们使用 React 应用程序设置了一个前端文件夹,现在我们希望将其设为服务。让我们创建一个 encore.service.ts 文件并添加以下代码来告诉 Encore 将前端文件夹视为“前端”服务。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
我们有两个选择:
为了服务 React 应用程序,我们需要在 Encore 中将其构建并作为静态资产提供。让我们在前端文件夹中设置 static.ts 文件。
在 Encore.ts 中提供静态文件与常规 API 端点类似,但我们使用 api.static 函数代替。
encore app create
这里有两件重要的事情需要注意:我们正在传递路径和目录选项。
太好了,静态端点已设置。现在,让我们为 React 应用程序安装一些依赖项
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
然后使用以下代码更新 main.tsx。
{ "id": "real-time-dashboard-<random-id>", "lang": "typescript" }
接下来,让我们设置 Tailwind CSS 并更新一些文件。
# create dashboard folder mkdir dashboard # switch to dashboard folder cd dashboard # create encore.service.ts file inside dashboard folder touch encore.service.ts
更改 tailwind.config.js 中的内容部分
import { Service } from 'encore.dev/service'; export default new Service('dashboard');
和带有以下代码的index.css。
# make sure you are in dashboard folder touch dashboard.ts
现在让我们为销售仪表板创建一些组件。
# 1_first_migration.up.sql CREATE TABLE sales ( id BIGSERIAL PRIMARY KEY, sale VARCHAR(255) NOT NULL, total INTEGER NOT NULL, date DATE NOT NULL );
这里,我们从生成的客户端导入类型,以匹配仪表板服务类型并确保类型安全。
# dashboard.ts import { SQLDatabase } from 'encore.dev/storage/sqldb'; import postgres from 'postgres'; const db = new SQLDatabase('dashboard', { migrations: './migrations', }); const client = postgres(db.connectionString);
# dashboard.ts ... // Map to hold all connected streams const connectedStreams: Map<string, StreamOut<Sale>> = new Map(); interface HandshakeRequest { id: string; } interface Sale { sale: string; total: number; date: string; } interface ListResponse { sales: Sale[]; }
为了产生销售额,我们需要一些模拟数据,所以让我们创建一个 src/constant.ts 文件并添加模拟数据
# dashboard.ts ... import { api, StreamOut } from 'encore.dev/api'; import log from 'encore.dev/log'; ... export const sale = api.streamOut<HandshakeRequest, Sale>( { expose: true, auth: false, path: '/sale' }, async (handshake, stream) => { connectedStreams.set(handshake.id, stream); try { await client.listen('new_sale', async function (data) { const payload: Sale = JSON.parse(data ?? ''); for (const [key, val] of connectedStreams) { try { // Send the users message to all connected clients. await val.send({ ...payload }); } catch (err) { // If there is an error sending the message, remove the client from the map. connectedStreams.delete(key); log.error('error sending', err); } } }); } catch (err) { // If there is an error reading from the stream, remove the client from the map. connectedStreams.delete(handshake.id); log.error('stream error', err); } } );
# dashboard.ts ... ... export const addSale = api( { expose: true, method: 'POST', path: '/sale/add' }, async (body: Sale & { id: string }): Promise<void> => { await db.exec` INSERT INTO sales (sale, total, date) VALUES (${body.sale}, ${body.total}, ${body.date})`; await client.notify( 'new_sale', JSON.stringify({ sale: body.sale, total: body.total, date: body.date }) ); } );
在这里,我们导入 getRequestClient,然后从仪表板服务调用 addSale 端点。它非常简单,并且 addSale 是类型安全的,因此如果您尝试传递任何不允许的属性,您将收到错误。
接下来,让我们创建一个 SalesDashboard 组件来显示包含销售指标、近期销售和历史销售的仪表板视图。
# macOS brew install encoredev/tap/encore # Windows iwr https://encore.dev/install.ps1 | iex # Linux curl -L https://encore.dev/install.sh | bash
SalesDashboard 采用一个名为 role 的道具,它决定是否显示GenerateSales 组件。
saleStream 将保存活动流引用并且是强类型的。
encore app create
安装组件时,我们使用仪表板服务的销售端点创建流连接。然后,我们监听套接字打开和关闭事件,并根据这些事件运行适当的逻辑。
我们从 saleStream.current 中读取销售数据并将其存储在centreSalesData 状态中。
当组件卸载时,我们清理并关闭当前流。
Select language for your applicatio : TypeScript Template: Empty app App Name : real-time-dashboard
此代码使用仪表板服务中的 listSales 端点获取存储的销售额,并将其保存在 salesData 状态中。
{ "id": "real-time-dashboard-<random-id>", "lang": "typescript" }
此代码计算近期销量和历史销量数据。
# create dashboard folder mkdir dashboard # switch to dashboard folder cd dashboard # create encore.service.ts file inside dashboard folder touch encore.service.ts
最后,使用此代码更新 App.tsx 文件。
import { Service } from 'encore.dev/service'; export default new Service('dashboard');
这里,我们根据角色查询参数是否可用来显示 SalesDashboard 和 RoleSelector 组件。
现在,让我们通过在前端根目录中运行以下命令来构建 React 应用程序。
# make sure you are in dashboard folder touch dashboard.ts
成功运行命令后,将在前端目录中创建 dist 文件夹。
太好了,现在在下一部分中,让我们运行应用程序并从头到尾对其进行测试。
运行 encore 应用程序很简单;只需使用下面的命令即可。
# 1_first_migration.up.sql CREATE TABLE sales ( id BIGSERIAL PRIMARY KEY, sale VARCHAR(255) NOT NULL, total INTEGER NOT NULL, date DATE NOT NULL );
成功运行命令后,您将在终端中看到如下日志:
# dashboard.ts import { SQLDatabase } from 'encore.dev/storage/sqldb'; import postgres from 'postgres'; const db = new SQLDatabase('dashboard', { migrations: './migrations', }); const client = postgres(db.connectionString);
在浏览器中访问http://127.0.0.1:4000,您将看到如下屏幕。
接下来,在一个选项卡中选择“查看器”,在另一个选项卡中选择“管理器”。
在检查开发仪表板时,我们创建了一条销售记录,并将其保存在数据库中,因此在 UI 中也可见。
现在,从经理视图中,单击“生成销售”按钮,并观看仪表板上的两个选项卡实时更新。
在本教程中,我们使用 React 和 Encore.ts 创建了一个实时销售仪表板。该应用程序会立即更新新的销售和库存商品,有助于快速决策。我们使用开源框架 Encore.ts 来使用 TypeScript 构建后端,以实现安全、流畅的编码。 Encore 的主要特点是:
这些功能结合在一起,可以更轻松地构建和管理复杂的应用程序,从而提供出色的开发人员体验。
以上是如何使用 Encore.ts 和 React 构建实时仪表板的详细内容。更多信息请关注PHP中文网其他相关文章!