PGlite 简介与使用:在浏览器和 Node.js 中运行真正的 PostgreSQL

发布时间: 更新时间: 总字数:3270 阅读时间:7m 作者:IP:上海 网址

PGlite 是 ElectricSQL 开源的嵌入式 PostgreSQL:将完整的 Postgres 编译为 WebAssembly(WASM)后打包成 TypeScript 客户端库,可零后端运行在浏览器、Node.js、Bun 与 Deno 中。本文梳理其核心特性与限制,演示如何用 pglite-socket 配合 psql 命令行操作本地数据目录,并给出 Node.js 与 Python(py-pglite)的可执行示例与适用场景。

PGlite 是什么

PGlite 由 ElectricSQL(Electric)开发,本质上是 Postgres 的 WASM 构建(其编译基础来自 Neon 的 Stas Kelvich 对 Postgres 的 fork),打包成 TypeScript 客户端库后可以在 浏览器、Node.js、Bun 或 Deno 中直接运行,无需安装任何后端数据库服务。

需要注意的是,PGlite 是单连接数据库(single user/connection)——它没有传统 Postgres 的多客户端并发服务模型,每个实例同时只服务一个连接。

核心特性

  1. 轻量且免虚拟机:不同于早期"浏览器里跑 Linux 虚拟机再跑数据库"的笨重方案,PGlite 直接将 Postgres 编译为 WASM,Gzip 压缩后体积约 3MB,可毫秒级启动。
  2. 纯正的 PostgreSQL:它不是简化的类 SQL 存储(如 SQLite 或 WebSQL),拥有真实 Postgres 的 SQL 语义,支持复杂 JOIN、索引、JSON 运算符等完整功能。
  3. 灵活的数据持久化:
    • 纯内存模式:new PGlite() 不传参数即内存模式,数据随实例关闭而释放,适合测试或临时缓存。
    • 浏览器端:通过 IndexedDB 持久化,传入 idb://my-pgdata 即可跨页面刷新保留数据。
    • Node/Bun/Deno 端:传入本地目录路径 ./path/to/pgdata 即可将数据落盘。
  4. 支持扩展(Extensions):支持动态加载 Postgres 扩展,包括当前 AI 开发中最常用的向量插件 pgvector,以及空间数据插件 PostGIS。
  5. Local-First 与响应式:官方定位是"基于 Postgres 构建响应式、实时、本地优先(Local-First)应用",配合 Electric 的同步引擎可将本地数据与远端 Postgres 服务器做双向同步;同时支持 Live Query(实时查询)能力。

通过 psql 命令行操作本地 PGlite 数据

借助官方的 @electric-sql/pglite-socket 包,可以把 PGlite 数据目录挂载为一个 Postgres 协议的 Socket 服务,再用系统自带的 psql(或 DBeaver、DataGrip 等图形工具)连进去,操作体验与 sqlite3 命令行类似。

步骤 1:通过 npx 启动 PGlite 引擎并挂载本地数据目录(例如 ./my_pgdata):

bash
npx @electric-sql/pglite-socket --db=./my_pgdata --port=54322

(此时终端会挂起,PGlite 引擎已在后台接管该目录的读写。不传 --db 则默认打开内存数据库 memory://。)

步骤 2:打开新的终端,用 psql 连接。由于 PGlite Socket 不支持 SSL,需要禁用 SSL 协商:

bash
PGSSLMODE=disable psql -h localhost -p 54322 -U postgres -d postgres

连接后即可像操作普通 Postgres 一样执行 SELECT * FROM ...,所有修改都会持久化到 ./my_pgdata 目录中。

常用参数速查(pglite-socket --help 可查看完整列表):

参数说明默认值
-d, --db数据库路径(目录即持久化,memory:// 为内存)memory://
-p, --portTCP 监听端口5432
-h, --host绑定地址127.0.0.1
-u, --pathUnix Domain Socket 路径(优先于 host:port)无
-e, --extensions逗号分隔的扩展列表(如 pgvector)无
-m, --max-connections最大并发连接数(内部多路复用)1

[!WARNING] PGlite 是单连接数据库,pglite-socket 内部通过多路复用模拟并发,官方明确说明"并非所有用例都能保证工作"。它适合本地开发、调试与测试,不适合作为多用户生产服务。

Node.js 使用示例

先在项目(前端工程或 Node.js 项目均可)中安装依赖:

bash
npm install @electric-sql/pglite

创建 index.mjs(使用原生 ESM 语法),贴入以下代码运行:

javascript
import { PGlite } from '@electric-sql/pglite';

async function main() {
  console.log('正在启动 PGlite...');

  // 1. 初始化数据库
  // 纯内存模式:
  const db = new PGlite();

  // 如需持久化:
  // 浏览器中:const db = new PGlite('idb://my-tasks-db');
  // Node.js 中:const db = new PGlite('./my-tasks-db');

  // 2. 执行批量 SQL:建表与插入数据(.exec 适合一次执行多条 SQL 语句)
  await db.exec(`
    CREATE TABLE IF NOT EXISTS tasks (
      id SERIAL PRIMARY KEY,
      task TEXT NOT NULL,
      done BOOLEAN DEFAULT false
    );

    INSERT INTO tasks (task, done) VALUES ('学习 PGlite 的基本原理', true);
    INSERT INTO tasks (task) VALUES ('开发本地优先 (Local-First) 应用');
    INSERT INTO tasks (task) VALUES ('结合 pgvector 测试大模型向量检索');
  `);
  console.log('表已创建并插入测试数据!');

  // 3. 参数化查询(.query 适合安全的参数化查询)
  // 获取未完成的任务(done = false)
  const result = await db.query('SELECT * FROM tasks WHERE done = $1;', [false]);

  // 4. 输出查询结果
  console.log('\n待办事项列表:');
  console.table(result.rows);
}

main().catch(console.error);

运行方式:

bash
node index.mjs
# 或在 package.json 中声明 "type": "module" 后直接 node index.js

运行效果(毫秒级启动,console.table 打印格式化表格):

text
正在启动 PGlite...
表已创建并插入测试数据!

待办事项列表:
┌─────────┬────┬───────────────────────────────────┬───────┐
│ (index) │ id │ task                              │ done  │
├─────────┼────┼───────────────────────────────────┼───────┤
│    0    │ 2  │ '开发本地优先 (Local-First) 应用'  │ false │
│    1    │ 3  │ '结合 pgvector 测试大模型向量检索' │ false │
└─────────┴────┴───────────────────────────────────┴───────┘

Python 使用示例(py-pglite)

PGlite 官方主要集中在 JavaScript/TypeScript 生态,Python 侧社区提供了封装库 py-pglite(作者 Wey Gu)。它在底层拉起 PGlite 的 WASM 引擎并暴露标准的 PostgreSQL 连接(默认走 Unix Domain Socket),让 Python 像 SQLite 一样即开即用真正的 Postgres,目前主要定位是自动化测试与轻量本地开发。

安装依赖

推荐使用 extra 一次装齐 SQLAlchemy 与 psycopg 3 驱动(SQLAlchemyPGliteManager.get_engine() 默认驱动为 psycopg,即 psycopg 3):

bash
pip install 'py-pglite[sqlalchemy]' psycopg[binary]

前置要求:本机需安装 Node.js 运行时(py-pglite 通过 node 子进程拉起 PGlite WASM 引擎,Node 依赖会自动安装)。

可运行示例(test_pglite.py)

python
from pathlib import Path

from py_pglite import PGliteConfig
from py_pglite.sqlalchemy import SQLAlchemyPGliteManager
from sqlalchemy import text


def main():
    # 1. 配置 PGlite:指定工作目录,并禁止退出时清理
    config = PGliteConfig(
        work_dir=Path("./my_local_pgdata"),  # Node.js 运行时环境目录
        cleanup_on_exit=False,               # 不清理 socket/进程等运行时文件
    )

    print(f"正在启动本地 PGlite,工作目录: {config.work_dir.absolute()}")

    # 2. 启动 Manager(上下文管理器,退出时自动停止服务)
    with SQLAlchemyPGliteManager(config) as manager:
        # 获取标准的 SQLAlchemy Engine(默认 psycopg3 驱动,单连接共享实例)
        engine = manager.get_engine()

        with engine.connect() as conn:
            # === 建表(如果不存在) ===
            conn.execute(text("""
                CREATE TABLE IF NOT EXISTS notes (
                    id SERIAL PRIMARY KEY,
                    content TEXT,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                );
            """))

            # === 插入新数据 ===
            conn.execute(text("""
                INSERT INTO notes (content)
                VALUES ('这是一条写入本地 PGlite 的数据!');
            """))
            conn.commit()
            print("数据写入成功。")

            # === 查询并验证 ===
            result = conn.execute(text("SELECT * FROM notes"))
            print("\n数据库中的全部记录:")
            for row in result:
                print(f"[{row.id}] {row.content} (Time: {row.created_at})")


if __name__ == "__main__":
    main()

运行:

bash
python test_pglite.py

关于数据持久化的说明:py-pglite 生成的 PGlite 实例默认运行在内存模式,work_dir 只是 Node.js 运行时环境目录(存放 package.json、node_modules 与启动脚本),cleanup_on_exit=False 保留的也是这些运行时文件。若需要在 Python 侧真正把数据落盘,需要自行修改生成的工作脚本、为 new PGlite() 传入数据目录(参见上文 Node.js 持久化方式),或仅将其作为 pytest 一次性测试数据库使用——这正是该库的主要设计定位。

适用场景总结

  • Local-First 应用:用户离线可用,操作保存在本地 PGlite,有网络时再通过同步引擎无感同步到云端 Postgres。
  • 轻量级演示或沙盒环境:在博客或文档页面直接内嵌可交互的 SQL 演练环境,无需后端 API。
  • 自动化测试环境:每次测试用内存模式瞬间拉起一个真实 Postgres 实例(如 py-pglite 配合 pytest),无需配置 Docker 容器。
  • 浏览器插件 / 桌面端套壳(Electron/Tauri):需要嵌入式关系型数据库时,PGlite 相比 SQLite 提供了完整的 Postgres 生态(扩展、JSON 运算符、pgvector 等)。

限制与注意事项

  • 单连接模型:PGlite 同一实例只支持一个连接,高并发场景需要外部排队或多路复用(pglite-socket 的 --max-connections 即为此设计)。
  • 不支持 SSL:pglite-socket 走的是本地开发场景,客户端连接需显式 sslmode=disable。
  • 不适合作为生产服务器后端:它的定位是嵌入式数据库(类比 SQLite 之于 MySQL),多用户服务端场景请使用标准 PostgreSQL。

参考

  1. https://github.com/electric-sql/pglite
  2. https://github.com/electric-sql/pglite-socket
  3. https://pypi.org/project/py-pglite/