前后端数据同步
聊到实时数据同步,很多团队会先想到WebSocket那一套方案,但实际落地时,选型往往是个头疼事。下面分享一个基于Electric的实践思路。
后端
后端这边,用的是PostgreSQL来存数据,配合RESTful API提供数据接口。同时,为了做到实时推送,直接开了个SSE(Server-Sent Events)连接。这套组合拳打下来,既保证了常规的数据请求能力,也铺好了实时更新的“高速通道”。

前端
前端这边借助Electric来实现本地数据的存储和管理。常规请求依然用RESTful接口,但实时推送这块,全仰仗SSE连接。
前端用的Electric库是 @electric-sql/client,主要会用到 Shape 和 ShapeStream 这两个核心概念。具体怎么用?看下面这段代码就能明白。
import { Shape, ShapeStream } from '@electric-sql/client'export interface IElectricShapeOption {
authorization: string
table: string
where: string
subscribe?: boolean
columns?: string[]
}export const createShapeStreamOptions = (option: IElectricShapeOption) => {
const { subscribe = true } = option
return {
// 后端接口地址
url: `${import.meta.env.VITE_APP_API_BASEURL}api/v1/shape`,
headers: {
Authorization: option.authorization,
},
params: {
table: option.table, // 同步的表名
where: option.where, // 同步的条件
columns: option.columns, // 需要同步的列,不设置就是同步所有的 设置了就只同步指定的列
},
subscribe, // 是否订阅实时数据推送,默认为 true
liveSse: true, // 是否使用 sse 连接,默认为 true 开启 sse 连接后会自动处理连接断开和重连逻辑
}
}async function useElectricShape(option: IElectricShapeOption) {
const rows = ref() const stream = new ShapeStream(createShapeStreamOptions(option))
const shape = new Shape(stream)
rows.value = await shape.rows as T[] shape.subscribe((callback) => {
rows.value = callback.rows as T[]
}) const destroy = async () => {
shape.unsubscribeAll()
} return { rows, destroy }
}
代码中,通过 ShapeStream 创建了一个流,然后实例化 Shape 来拿到所有数据。订阅后,数据每次变化都会自动更新到本地的 rows 里。最后别忘了提供一个 destroy 方法来清理订阅,防止内存泄露。
为什么选择 Electric
实时数据同步:靠SSE连接,后端数据一变,前端能立刻感知。这个特性非常适合需要频繁刷新的场景。
本地数据管理:Shape 和 ShapeStream 这两个东西,把数据管理和同步逻辑包装得挺规整,上手就能用。
易用性:API比较简单,几行代码就能搞定。对于快速迭代的项目来说,这点很重要,也减少了不小开发成本。
实际应用场景
- CRM 系统:客户的联系记录、状态变化,需要实时同步,团队成员才能拿到最新的数据。
- 电商平台:订单状态、库存变化,这类高频率更新的数据,实时同步是刚需。
- 数据分析平台:数据从采集到呈现,环节多、延迟要求高,实时同步能改善用户体验。
存在的问题
数据量一旦上去,性能可能会成为瓶颈。它并非万能,合理设计数据同步的条件和频率是关键。同步太多、太频繁,都是坑。
优化方案
数据懒加载:对于数据量大的列,不用一开始就全量拉下来。可以在需要用到时才调用API去加载,这样能极大减轻初始加载的压力。比如列表分开加载、详情页才拉取关联数据。这种“按需分配”的套路,在实践里效果很明显。
