Apache PouchDB 9.0.0 介绍与入门指南

Apache PouchDB 9.0.0 介绍与入门:孵化状态核实(官网页脚声明与 pouchdb.com 仅跳转的事实)、浏览器/Node.js 嵌入式文档数据库定位与 offline-first 同步核心卖点、npm 安装与依赖链(level/leveldown/uuid)、info/put/post/bulkDocs/allDocs/changes/replicate 与 memory 适配器全流程实测、LevelDB 落盘形态与 deprecated 警告解读

Apache PouchDBPouchDBApacheJavaScript数据库NoSQL2026/10/15

Apache PouchDB 9.0.0 介绍与入门指南

目标:介绍 Apache PouchDB——一个可运行在浏览器与 Node.js 中的开源 JavaScript 文档数据库,以本地离线存储(offline-first)加与 CouchDB 及兼容服务器同步为核心卖点;覆盖孵化状态核实、项目定位、核心概念与数据模型、9.0.0 版本的 npm 安装与依赖链、Node 20 下 info/put/post/bulkDocs/allDocs/changes/replicate 与 memory 适配器的全流程上手实测、LevelDB 落盘形态、适用场景与常见问题。官方信息核实与全部命令均在 Ubuntu 22.04 环境于 2026-10-15 实测完成;浏览器端接入方式本文未实测,以官方文档为准。

⚠️ 提示:Apache PouchDB 目前处于 Apache 孵化器(Incubator)孵化阶段,官方名称即 "Apache PouchDB (incubating)"。官网页脚声明明确指出项目 "has yet to be fully endorsed by the ASF"(原文见 2.2 节)。评估选型时请将孵化状态与潜在 API 变动纳入考量。

一、环境信息

  • 操作系统:Ubuntu 22.04(x86_64)
  • Node.js:v20.20.2(NodeSource setup_20.x 安装,网络受限环境经代理执行)
  • npm:10.8.2(随 Node.js 附带)
  • PouchDB:9.0.0(npm latest tag,与官网 Download v9.0.0 一致)
  • 实验工作目录:/opt/pouchdb-demo(npm 初始化目录,落盘数据库目录亦在此)
  • 信息核实方式:官网 pouchdb.apache.org 页面与 npm registry 均于 2026-10-15 当日抓取
  • 实测边界:Node.js 端全流程实测(本地 LevelDB 存储、文档增删改查、批量写入、范围查询、变更流、本地复制、内存适配器、落盘形态);浏览器端接入未实测,相关描述仅为官方定位转述

二、定位与孵化状态

2.1 项目定位(官方原文)

官网 https://pouchdb.apache.org/ 首页(2026-10-15 实测抓取)关键信息:

  • 页面标题:Apache PouchDB™, the JavaScript Database that Syncs!
  • 首页下载按钮:Download v9.0.0;slogan:The Database that Syncs!
  • 定位原文一:"PouchDB is an open-source JavaScript database inspired by Apache CouchDB that is designed to run well within the browser"
  • 定位原文二:"store data locally while offline, then synchronize it with CouchDB and compatible servers when back online"

拆解这段定位,得到四个关键词:

  • 嵌入式文档数据库:以 JavaScript 库形态嵌入应用进程(浏览器或 Node.js),无需独立部署数据库服务,数据以 JSON 文档形式存取;
  • offline-first(本地先行):数据先存本地,离线时照常读写;
  • 同步是核心卖点:回到在线后与 CouchDB 及兼容服务器同步("The Database that Syncs!"),即与 CouchDB 协议兼容;
  • CouchDB 血统:inspired by Apache CouchDB。

2.2 孵化状态(必须知晓)

pouchdb.com 现在只是跳板页:实测其原始 HTML 仅为一条 meta 刷新跳转:

<meta http-equiv="refresh" content="0; url=https://pouchdb.apache.org/">

写文档、引用资料一律认准 **https://pouchdb.apache.org/**(实测中经跳转页抓取曾拿到旧站缓存内容,判断须以原始 HTML 为准)。

官方页脚孵化声明原文(2026-10-15 逐字抓取自 pouchdb.apache.org):

Apache PouchDB (incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Incubator. Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications, and decision making process have stabilized in a manner consistent with other successful ASF projects. While incubation status is not necessarily a reflection of the completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF.

即:孵化状态不必然反映代码的完整性与稳定性,但表明项目尚未获得 ASF 完全背书。

三、核心概念与数据模型

3.1 文档模型:_id 与 _rev

PouchDB 存储的最小单元是 JSON 文档,每篇文档带两个系统字段:

  • _id:文档唯一标识。put 时自行指定(实测 fruit:apple);post 不带 _id 时自动生成 uuid(实测 8b897ba3-8b88-403f-a2a2-6b324d040773);
  • _rev:文档修订版本号(MVCC 乐观锁)。新建为 1-…,更新必须携带最新 _rev,成功后递增为 2-…(实测 1-fd159f80… → 2-bfbad433…)。

allDocs 结果按 _id 字典序排列(实测见 5.5 节)。

3.2 适配器(adapter)

同一套 API 之下,PouchDB 用适配器对接不同的底层存储:

适配器底层标识(实测 info() 输出)本文实测情况
leveldb(Node.js 默认)backend_adapter: LevelDOWN、adapter: leveldb实测:落盘为标准 LevelDB 目录(5.9 节)
memorybackend_adapter: MemDOWN、adapter: memory实测:纯内存,进程退出即丢数据(5.8 节)
浏览器端适配器—本文未实测,以官方文档为准

3.3 同步与复制

复制(replication)是 PouchDB 的招牌能力:db.replicate.to(...) 可把数据复制到另一个库(实测本地库 → 本地 backup-db,见 5.7 节);生产场景中复制目标通常是与 CouchDB 协议兼容的服务器(官方定位原文 "synchronize it with CouchDB and compatible servers")。远端服务器同步本文未实测。

3.4 变更流(changes feed)

每个库维护一个按 seq 递增的变更序列,db.changes({since: ...}) 可增量获取变更(实测 since:0 一次性取回全部,见 5.6 节)——这是同步与监听数据变化的基础机制。

四、安装

4.1 准备 Node.js 环境(已有可跳过)

curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt-get install -y nodejs

实测安装日志可见 Setting up nodejs (20.20.2-1nodesource1) ...;验证版本:

node --version
npm --version
v20.20.2
10.8.2

4.2 核实最新版本

npm view pouchdb version
npm view pouchdb dist-tags
9.0.0
{ latest: '9.0.0' }

npm 上 PouchDB 最新稳定版为 9.0.0(latest tag),与官网 Download v9.0.0 一致。

4.3 安装 pouchdb

cd /opt/pouchdb-demo
npm init -y && npm install pouchdb

实测输出:

npm warn deprecated abstract-leveldown@7.2.0: Superseded by abstract-level
npm warn deprecated leveldown@5.6.0: Superseded by classic-level
npm warn deprecated leveldown@6.1.1: Superseded by classic-level
added 66 packages, and audited 67 packages in 6s
2 moderate severity vulnerabilities

确认安装版本:

node -e "console.log(require('pouchdb/package.json').version)"
9.0.0

4.4 依赖链一览

pouchdb 9.0.0 的 package.json 声明 14 个直接依赖(npm 实装 66 个包):

依赖版本
level6.0.1
levelup4.4.0
leveldown6.1.1
uuid8.3.2
node-fetch2.6.9
fetch-cookie2.2.0
spark-md53.0.2
level-codec9.0.2
level-write-stream1.0.0
ltgt2.2.1
double-ended-queue2.1.0-0
readable-stream1.1.14
through23.0.2
vuvuzela1.0.3

要点:Node 端本地存储基于 level 6.0.1(levelup 4.4.0 + leveldown 6.1.1)——实测 info() 的 backend_adapter: LevelDOWN 即来自 leveldown;自带 uuid 8.3.2 供 post 自动生成 _id(实测见 5.3 节)。

4.5 deprecated 警告解读(坑)

npm install 时出现 3 条 deprecated 警告(见 4.3 输出):abstract-leveldown 7.2.0 / leveldown 5.6.0 / leveldown 6.1.1 被上游 Level 官方的 classic-level / abstract-level 取代——PouchDB 9.0.0 仍在使用旧的 level 依赖链。警告属上游依赖链提示,不影响功能;另有 npm audit 报 2 个 moderate 漏洞提示,可自行评估(本文未深入)。

五、上手实测

5.0 实测总览

编写 demo.js(覆盖 info / put / post / bulkDocs / allDocs / changes / replicate / memory 八组操作,与输出编号一一对应),一次跑通:

node demo.js

完整实测输出(逐行照录):

=== 1. db.info() of demo-db ===
{
  "doc_count": 0,
  "update_seq": 0,
  "backend_adapter": "LevelDOWN",
  "db_name": "demo-db",
  "auto_compaction": false,
  "adapter": "leveldb"
}

=== 2. put / get / update ===
put result: {"ok":true,"id":"fruit:apple","rev":"1-fd159f802200fceb52418310bedd8071"}
get result: {"name":"Apple","color":"red","_id":"fruit:apple","_rev":"1-fd159f802200fceb52418310bedd8071"}
update result: {"ok":true,"id":"fruit:apple","rev":"2-bfbad4332fd41669d75330d7bc51b166"}
get after update: {"name":"Apple","color":"green","_id":"fruit:apple","_rev":"2-bfbad4332fd41669d75330d7bc51b166"}

=== 3. post (auto _id) ===
post result: {"ok":true,"id":"8b897ba3-8b88-403f-a2a2-6b324d040773","rev":"1-c060b5de915c45809dfe46dfa98c39c9"}
get posted doc: {"name":"AutoIdDoc","kind":"post-test","_id":"8b897ba3-8b88-403f-a2a2-6b324d040773","_rev":"1-c060b5de915c45809dfe46dfa98c39c9"}

=== 4. bulkDocs (fruits) ===  —— 6 条水果文档全部 ok:true(banana/cherry/grape/lemon/mango/peach,各 rev 1-…)

=== 5a. allDocs include_docs:true (full) ===
total_rows: 8 rows: 8
   8b897ba3-8b88-403f-a2a2-6b324d040773 -> "AutoIdDoc"
   fruit:apple -> "Apple"
   fruit:banana -> "Banana"
   fruit:cherry -> "Cherry"
   fruit:grape -> "Grape"
   fruit:lemon -> "Lemon"
   fruit:mango -> "Mango"
   fruit:peach -> "Peach"

=== 5b. allDocs startkey/endkey range (fruit:banana..fruit:grape) ===
   fruit:banana
   fruit:cherry
   fruit:grape

=== 5c. allDocs key single (fruit:lemon) ===
rows: 1 ["fruit:lemon"]

=== 6. changes({since:0}) one-shot ===
last_seq: 9 results: 8
  seq: 2 id: fruit:apple deleted: undefined
  seq: 3 id: 8b897ba3-8b88-403f-a2a2-6b324d040773 deleted: undefined
  seq: 4 id: fruit:banana deleted: undefined
  seq: 5 id: fruit:cherry deleted: undefined
  seq: 6 id: fruit:grape deleted: undefined
  seq: 7 id: fruit:lemon deleted: undefined
  seq: 8 id: fruit:mango deleted: undefined
  seq: 9 id: fruit:peach deleted: undefined

=== 7. replicate.to(backup-db) ===
replicate result: {"docs_read":8,"docs_written":8,"doc_write_failures":0}
backup-db info: {
  "doc_count": 8,
  "update_seq": 8,
  "backend_adapter": "LevelDOWN",
  "db_name": "backup-db",
  "auto_compaction": false,
  "adapter": "leveldb"
}

=== 8. memory adapter ===
mem adapter: memory
mem get: {"msg":"in-memory","_id":"mem:hello","_rev":"1-b5cf42d27817e6e9a77c8d49a18acf7b"}
mem info: {"doc_count":1,"update_seq":1,"backend_adapter":"MemDOWN","db_name":"mem","auto_compaction":false,"adapter":"memory"}
=== ALL DONE ===

5.1 info():库信息

新建库 demo-db 的 db.info() 实测:doc_count=0、update_seq=0、backend_adapter=LevelDOWN、adapter=leveldb、auto_compaction 默认 false。

5.2 put / get / 带 rev 更新

  • put 返回 ok:true 与修订号 1-fd159f80…;
  • 更新必须携带最新 _rev,成功后修订号变为 2-bfbad433…;
  • get 读回验证:color 由 red 改为 green 生效。

5.3 post:自动生成 uuid

post 不带 _id 时自动生成 uuid(实测 8b897ba3-8b88-403f-a2a2-6b324d040773),返回各自的 1-… 修订号。

5.4 bulkDocs:批量写入

6 条水果文档(banana/cherry/grape/lemon/mango/peach)一次插入,逐条返回 ok:true 与各自 rev 1-…。

5.5 allDocs:全量、范围与单键查询

  • 全量:8 行,按 _id 字典序返回(uuid 文档排在 fruit: 前缀之前);
  • 范围:startkey='fruit:banana'、endkey='fruit:grape' 返回 3 行(含端点);
  • 单键:key='fruit:lemon' 精确返回 1 行。

5.6 changes:变更流

changes({since:0}) 一次性 feed 返回 last_seq=9、8 条结果。注意:同一文档的多次修改在 feed 中合并为一条(按最新 seq),故 fruit:apple 显示 seq 2(即其第二次写,首次写入的 seq 1 不再单独出现);results 数等于文档数而非写操作数。

5.7 replicate:本地复制

db.replicate.to('backup-db') 本地 → 本地复制实测:docs_read=8 / docs_written=8 / doc_write_failures=0;随后 backup-db.info() 验证 doc_count=8,适配器同为 leveldb/LevelDOWN。

5.8 memory 适配器

PouchDB.plugin(require('pouchdb-adapter-memory'));
new PouchDB('mem',{adapter:'memory'})

实测 put/get 正常,backend_adapter=MemDOWN;进程退出即丢数据,仅适合临时计算/缓存场景。

5.9 落盘形态:标准 LevelDB 目录

new PouchDB('demo-db')(相对路径)在工作目录下创建同名目录:

ls -la /opt/pouchdb-demo
drwxr-xr-x  5 root root  4096 Oct 14 19:26 .
drwxr-xr-x  2 root root  4096 Oct 14 19:26 backup-db
drwxr-xr-x  2 root root  4096 Oct 14 19:26 demo-db
-rw-r--r--  1 root root  3927 Oct 14 19:26 demo.js
drwxr-xr-x 75 root root  4096 Oct 14 19:26 node_modules
-rw-r--r--  1 root root 38192 Oct 14 19:26 package-lock.json
-rw-r--r--  1 root root   315 Oct 14 19:26 package.json
ls -la demo-db/
-rw-r--r-- 1 root root 4937 Oct 14 19:26 000003.log
-rw-r--r-- 1 root root   16 Oct 14 19:26 CURRENT
-rw-r--r-- 1 root root    0 Oct 14 19:26 LOCK
-rw-r--r-- 1 root root   57 Oct 14 19:26 LOG
-rw-r--r-- 1 root root   50 Oct 14 19:26 MANIFEST-000002

内部是标准 LevelDB 文件布局:000003.log(写前日志)、CURRENT、LOCK、LOG、MANIFEST-000002;backup-db 目录同构。

六、适用场景与局限

适用场景:

  • offline-first Web 应用:浏览器端本地存储,断网可用、联网同步;
  • Node.js 侧嵌入式轻量文档存储:工具脚本、原型、单机小工具的 JSON 持久化;
  • 端云协同:端上 PouchDB + 服务端 CouchDB(及兼容服务器)的同步架构——同步是核心能力;
  • 需要变更流(changes)驱动 UI 实时更新的场景。

局限与注意:

  • 单机嵌入式定位:数据库嵌在应用进程内,不具备服务端多客户端并发访问、账号权限与运维体系;
  • 服务端场景应选 Apache CouchDB:PouchDB 的定位是端侧/进程内存储,服务端文档数据库交给 CouchDB 及兼容服务器;
  • memory 适配器进程退出即丢数据,不能当持久化存储用;
  • auto_compaction 默认 false(实测 info() 输出),压缩行为需按需配置;
  • 孵化期项目(2.2 节),API 与发布形态可能调整。

💡 选型对照(按各方官方定位描述归纳,本文未逐一实测):PouchDB——浏览器/Node.js 内嵌文档库,强项是本地存储与同步;Apache CouchDB——服务端文档数据库,是 PouchDB 复制协议的服务端;level/classic-level 等——更底层的 KV 存储库(PouchDB 9.0.0 的 Node 端存储基座)。要"端侧离线 + 同步"选 PouchDB;要"服务端多用户文档服务"选 CouchDB。

七、常见问题

Q1:pouchdb.com 打开的内容不对/像是旧站? pouchdb.com 现在只是 meta 跳转页(2.2 节实测),真实站点是 https://pouchdb.apache.org/ ;抓取判断以原始 HTML 为准。

Q2:npm install 的一串 deprecated 警告要紧吗? 3 条警告(abstract-leveldown 7.2.0、leveldown 5.6.0、leveldown 6.1.1)是上游 Level 生态转向 classic-level/abstract-level 的提示,PouchDB 9.0.0 仍用旧链,不影响功能(4.5 节);npm audit 的 2 个 moderate 提示可自行评估。

Q3:更新文档报错或不生效? 更新必须携带该文档当前最新的 _rev(MVCC 乐观锁),实测 1-… → 2-…(5.2 节)。

Q4:changes 的结果数和我的写操作数对不上? 同一文档的多次修改在 feed 中合并为一条(按最新 seq),results 数等于文档数而非写操作数(5.6 节实测说明)。

Q5:数据落在哪里? Node 端用相对路径库名时,会在工作目录创建同名目录,内部为标准 LevelDB 文件布局(000003.log / CURRENT / LOCK / LOG / MANIFEST-000002,5.9 节实测)。

Q6:浏览器端怎么引入? 本文未实测浏览器端,接入方式(打包引入/CDN 等)以官方文档为准;官方定位原文即 "designed to run well within the browser"。

参考链接