PGlite:让 PostgreSQL 运行在浏览器里

30次阅读

本文约 3000 字,阅读时间 8 分钟

PGlite 是什么?

PGlite 是用 WebAssembly(WASM)编译的 PostgreSQL,可以直接在浏览器、Node.js、Deno、Bun 等任何支持 WASM 的环境中运行,无需安装数据库服务器。

换句话说:你在浏览器里跑了一个完整的 PostgreSQL

传统架构:Browser → HTTP API → Backend Server → Database
                          ↑
                    这是瓶颈点
  • 所有数据操作必须经过服务器中转
  • 离线场景完全不可用
  • 每次读写都有网络延迟

Local-First 软件开发理念强调:

数据首先存储在本地设备,用户拥有完整控制权,网络是可选的增强而非必需。

代表项目:CapsuleDB、Liveblocks、Electric SQL

PGlite 就是这个趋势下的基础设施——把经过生产验证的 PostgreSQL 直接嵌入前端。

PostgreSQL C 代码
    ↓ 编译
Emscripten / wasm-pack
    ↓
WASM 字节码 (.wasm)
    ↓ 在 WASM 运行时中执行
浏览器 / Node.js / Deno

PGlite 基于 postgres-wasm 项目(由 Supabase 发起),在此基础上做了工程化封装。

特性 说明
完整 Postgres 语法 支持 SQL、事务、存储过程、扩展(PostGIS 等)
跨平台运行 浏览器、Node.js、Bun、Deno、Edge Workers
零运维 不需要安装,不需要配置,不需要连接云数据库
持久化可选 可以用 IndexedDB、File System API 或内存模式
大小可控 约 10MB(压缩后),首次加载后缓存
多语言绑定 JavaScript/TypeScript、Python、Rust 等
┌─────────────────────────────────────┐
│         应用层 Application          │
├─────────────────────────────────────┤
│       PGlite API (JS Binding)       │
├─────────────────────────────────────┤
│     PostgreSQL (WASM)               │
│  ┌──────────────────────────────┐   │
│  │ Query Planner / Executor     │   │
│  │ Storage Engine               │   │
│  │ Buffer Manager               │   │
│  │ Transaction Manager          │   │
│  └──────────────────────────────┘   │
├─────────────────────────────────────┤
│   持久化层(可选)│
│   IndexedDB / OPFS / Memory         │
└─────────────────────────────────────┘

痛点:数据分析工具必须联网,数据无法本地缓存

解决方案

  • 可以在浏览器里直接连接本地 CSV/Excel 文件
  • 用 SQL 做数据清洗和聚合
  • 结果可视化,导出报告

痛点:PWA(渐进式 Web 应用)缺乏本地数据库能力

解决方案

  • Service Worker 中运行 PGlite
  • 离线时写入本地,联网后同步到云端
  • 实现真正的离线优先体验

痛点:向量数据库往往需要额外的服务端部署

解决方案

  • 结合 pgvector 扩展,在浏览器内做向量相似度搜索
  • 实现本地 RAG(检索增强生成)pipeline

痛点:本地开发需要搭建 PostgreSQL 环境,配置繁琐

解决方案

  • 新项目一行代码初始化数据库
  • 每次测试都是干净的数据库状态
<!DOCTYPE html>
<html>
<head>

<title>PGlite Demo</title>
</head>
<body>
  <div id="result">Loading...</div>

  <script type="module">
    // 从 CDN 加载 PGlite
    import {PGlite} from 'https://cdn.jsdelivr.net/npm/@electric-sql/pglite/dist/index.js';

    async function main() {
      // 初始化数据库实例
      const db = new PGlite();

      // 等待数据库就绪
      await db.waitReady;

      // 执行 SQL
      const result = await db.query('SELECT version();');

      // 渲染结果
      document.getElementById('result').innerHTML =
        `
<pre>${result.rows[0].version}</pre>`;

      // 插入数据
      await db.query(`
        CREATE TABLE IF NOT EXISTS users (
          id SERIAL PRIMARY KEY,
          name TEXT NOT NULL,
          email TEXT UNIQUE
        );
      `);

      await db.query(`INSERT INTO users (name, email) VALUES ('张三', 'zhangsan@example.com');`);

      const users = await db.query('SELECT * FROM users;');
      console.log('Users:', users.rows);
      // 输出: [{id: 1, name: '张三', email: 'zhangsan@example.com'}]
    }

    main();
  </script>
</body>
</html>
npm install @electric-sql/pglite

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

const db = new PGlite();
// 或者指定持久化目录(Node.js 支持 OPFS)// const db = new PGlite('./my-data');

await db.waitReady;

// 完整的 SQL 查询
const result = await db.query(`
  WITH stats AS (
    SELECT
      date_trunc('day', created_at) AS day,
      COUNT(*) AS order_count,
      SUM(amount) AS total_amount
    FROM orders
    WHERE created_at >= NOW() - INTERVAL '30 days'
    GROUP BY 1
  )
  SELECT
    day,
    order_count,
    total_amount,
    ROUND(total_amount / NULLIF(order_count, 0), 2) AS avg_order_value
  FROM stats
  ORDER BY day DESC;
`);

console.log(result.rows);
import {PGlite} from '@electric-sql/pglite';

// 内存模式(每次刷新数据丢失)const memDb = new PGlite();

// IndexedDB 持久化(浏览器)const indexedDb = new PGlite('idb://my-database');

// OPFS 持久化(支持大文件,Node.js 18+ / 现代浏览器)const opfsDb = new PGlite('opfs://production-db');

测试环境:MacBook Pro M2,Chrome 120

操作 PGlite (WASM) 原生 Postgres 对比
SELECT(全表扫描 10 万行) ~80ms ~5ms 16x 慢
INSERT(单条) ~5ms ~0.5ms 10x 慢
事务(10 条 INSERT) ~45ms ~8ms 5.6x 慢
冷启动(加载 WASM) ~2s 仅首次

不是所有场景都适合用 PGlite 替代云数据库。

  • 对于 复杂查询和大数据量,WASM 版的性能差距仍然明显
  • 对于 日常增删改查、小型数据集(<10 万行),体验接近原生
  • 最佳定位:本地数据处理、离线缓存、开发环境 而非生产数据库
@electric-sql/pglite  内置支持以下扩展:├── pgvector      向量相似度搜索(AI/Embedding 应用)├── pg_stat_statements  查询性能分析
├── uuid-ossp     UUID 生成
├── hstore        K-V 存储
└── citext        大小写不敏感文本
工具 说明
Electric SQL 同步层,连接 PGlite 和云端 Postgres
Drizzle ORM 轻量级 ORM,天然支持 PGlite
Prisma 正在支持中
Postgres.js 纯 JS Postgres 客户端,可搭配 PGlite 使用
方案 架构 SQL 支持 体积 持久化 适用场景
PGlite WASM 完整 Postgres 100% ~10MB IDB/OPFS/Mem 通用本地数据库
SQLite WASM WASM SQLite 80% ~1MB IDB/OPFS/Mem 轻量 Web 应用
Dexie.js IndexedDB Wrapper ~100KB IndexedDB 简单 K-V 存储
Liveblocks 云端 + 本地缓存 受限 云优先 实时协作应用
  • 高并发写入(浏览器单线程瓶颈)

  • 大数据量分析(GB 级别数据)

  • 需要多用户同步(缺少内置同步机制,需配合 Electric SQL)

  • 对延迟敏感的生产服务(WASM 执行效率不如原生代码)

  • ⚠️ 不支持 prepared statements 缓存(影响高并发性能)

  • ⚠️ OPFS 在部分浏览器中仍为实验特性

  • ⚠️ 某些 Postgres 扩展(如 PostGIS)尚未完整移植

过去:Browser ──→ Server ──→ Database
现在:Browser ═══════════════ Database(直连,Server 仅同步)

PGlite 填补了「完整 SQL 能力」与「前端直连」之间的空白。

  1. WASM 运行时性能优化(WASM GC 提案落地后会有显著提升)
  2. 与 AI 能力结合(向量搜索 + 本地 RAG)
  3. 同步协议成熟(Electric SQL 的 sync protocol 是关键)
  4. 服务端渲染(SSR)集成(Next.js、Vite 插件支持)

PGlite 让 PostgreSQL 第一次真正 ” 入驻 ” 前端。 它不是要替代云数据库,而是开启了一种新的可能性:数据处理能力下沉到终端,让应用拥有真正的本地数据主权。

  1. Electric SQL 官方文档:https://electric-sql.com
  2. PGlite GitHub:https://github.com/electric-sql/pglite
  3. supabase / postgres-wasm:https://github.com/supabase/postgres-wasm
  4. PostgreSQL WASM 技术解析:WebAssembly 对数据库的意义(社区文章)
  5. Local-First Software:https://www.inkandswitch.com/local-first/

本文由飞熊增长运营官整理,保留所有版权。

正文完