☰
AFFiNE开源替代Notion:文档白板表格融合与本地优先部署实战
2026/9/26 19:03:21 网站建设 项目流程

1. 为什么我要认真聊聊 AFFiNE 这个项目

第一次听说 AFFiNE 是在一个开源社区的闲聊帖里,有人甩了一句“Notion 的下一代开源替代品”,底下跟了几十条讨论。我当时的第一反应是:又一个蹭 Notion 热度的项目罢了。毕竟这几年打着“Notion 替代”旗号的产品没有一百也有八十,大部分要么是套壳编辑器,要么功能残缺得厉害,用两天就弃了。

但 AFFiNE 不太一样。我花了一个周末把它从源码编译跑起来,又用了大概两周时间把日常的笔记、文档、简单的项目看板都迁移过去试了一遍,结论是:这东西确实值得认真对待。它不是简单的“开源版 Notion”,而是在文档和数据库的融合方式上走出了一条自己的路——把文档、白板、表格三种形态揉在同一个页面空间里,这个设计思路本身就很有意思。

这篇文章适合几类人看:一是对 Notion 这类一体化工作空间有需求、但又在意数据主权和长期可用性的朋友;二是想研究现代协同文档编辑器架构的开发者;三是单纯想找一个能自己部署、不依赖第三方服务的知识管理工具的人。我会从整体设计思路、核心技术点、实际部署和使用的完整流程、以及踩过的坑这几个维度展开,尽量把我知道的都倒出来。

需要提前说明的是,AFFiNE 目前仍在快速迭代中,我写的内容基于我实际使用的版本,后续版本可能有变化。另外,我不会把它吹成完美无缺的东西,该说的问题我也会直说。

2. 整体设计思路:文档、白板、表格为什么要揉在一起

2.1 传统笔记工具的“形态割裂”问题

用过 Notion 的人应该都有体会:写文档是一个页面,做看板是另一个页面,画流程图又得跳到白板工具里去。虽然 Notion 后来加了白板功能,但本质上还是几个独立模块拼在一起,数据之间没有真正的融合。你在文档里写了一段需求描述,想把它直接拖到白板上做头脑风暴,或者变成表格里的一行任务,操作起来是割裂的。

我自己的痛点特别明显。做项目规划的时候,我习惯先在白板上画架构草图,然后在文档里写详细说明,最后在表格里排任务和时间线。这三个东西在传统工具里是三份独立的数据,改了一处,另外两处不会自动同步。时间一长,白板上的图和文档里的描述就对不上了,维护成本很高。

AFFiNE 的设计思路就是冲着这个问题去的。它的核心概念叫“Edgeless”和“Page”两种模式的无缝切换。同一个内容块,你可以在文档视图里把它当成一段文字,切到白板视图里它就变成一个可以自由拖拽的卡片。底层数据是同一份,只是渲染方式不同。这个设计听起来简单,但实现起来涉及不少架构上的取舍。

2.2 底层数据模型的选择逻辑

AFFiNE 底层用的是 CRDT(Conflict-free Replicated Data Type,无冲突复制数据类型)来做协同编辑的数据同步。具体来说,它早期用的是 Yjs 这套库,后来自己做了不少封装和优化。为什么选 CRDT 而不是 OT(Operational Transformation)?这是个很关键的架构决策。

OT 的思路是:所有操作经过服务器排序后再分发,保证一致性。优点是成熟、很多协同编辑器都在用;缺点是强依赖中心服务器,离线场景处理起来很麻烦。CRDT 的思路是:每个操作本身携带足够的信息,任何顺序应用都能收敛到同一个状态。优点是天然支持离线编辑和点对点同步,缺点是数据体积会膨胀,对垃圾回收要求高。

AFFiNE 选择 CRDT,我认为核心原因是它想支持“本地优先”(Local-first)的使用方式。你可以完全离线在本地编辑,等联网后再同步,不会出现冲突丢失。这对那些经常在没网环境下工作、或者对数据隐私特别在意的人来说,是很实在的价值。当然代价就是同步的数据包会大一些,初次加载和长期使用后的存储优化需要额外处理。

2.3 块级编辑器的实现取舍

AFFiNE 的编辑器是基于块(Block)的,这点和 Notion 一样。但它的块模型比 Notion 更“扁平”一些。Notion 的块是严格树形嵌套的,一个块只能有一个父块。AFFiNE 在某些场景下允许块有多个引用关系,这就为白板模式下的自由布局提供了基础。

具体来说,AFFiNE 用了一个叫“BlockSuite”的编辑器框架,这是他们自己开源的。BlockSuite 把文档模型、编辑器视图、协同层做了比较清晰的分层。文档模型层定义块的结构和属性,编辑器视图层负责渲染和交互,协同层处理 CRDT 同步。这种分层的好处是,同一份文档模型可以对应多种视图——文档视图、白板视图、表格视图,都是不同的视图层实现,共享同一个模型层。

这个架构的优点是扩展性好,想加新的视图类型相对容易。缺点是初期开发复杂度高,各层之间的边界需要仔细设计,不然容易出现视图和模型不同步的 bug。我在使用过程中确实遇到过几次切换视图后内容显示异常的情况,刷新一下就好了,说明这块还在打磨中。

3. 核心技术点拆解:几个值得关注的实现细节

3.1 BlockSuite 编辑器框架的分层设计

BlockSuite 是 AFFiNE 团队开源出来的编辑器框架,可以单独使用。它的分层大概是这样的:

  • Model 层:定义块的数据结构,包括块的类型、属性、子块关系等。这一层不关心怎么渲染,只关心数据长什么样。
  • View 层:负责把 Model 渲染成用户能看到的界面。文档视图、白板视图、表格视图都是不同的 View 实现。
  • Command 层:定义各种操作命令,比如插入块、删除块、修改属性、移动块等。所有对文档的修改都通过命令来执行,方便做撤销重做和协同同步。
  • Sync 层:基于 CRDT 做多端同步,处理冲突合并。

这个分层的好处是职责清晰。比如我想加一个“思维导图视图”,只需要写一个新的 View 层实现,Model 和 Command 层基本不用动。坏处是抽象层次多了之后,调试起来比较绕。有一次我遇到一个块在白板视图里位置不对的问题,追了半天发现是 View 层的一个坐标转换计算有误,跟 Model 层的数据没关系。

3.2 CRDT 同步机制的实际表现

CRDT 在实际使用中的表现,我分几个场景来说:

单机离线编辑:完全没问题,所有操作都在本地完成,响应速度很快。AFFiNE 会把操作记录存在本地的 IndexedDB 里,等联网后再同步。

多端同时编辑:我试过两台电脑同时编辑同一个文档,一台改文字,一台拖白板上的卡片,同步后两边内容都正确合并了,没有出现丢失。但同步有延迟,大概几秒到十几秒不等,取决于网络状况和操作复杂度。

长时间使用后的性能:CRDT 的一个已知问题是操作历史会不断累积,导致文档加载变慢。AFFiNE 有做快照和压缩机制,但我用了一个月左右、文档里积累了几百个块之后,确实感觉打开速度比刚开始慢了一些。后来我手动整理了一下,把一些不再需要的编辑历史清理掉,速度就恢复了。所以建议定期做一下文档整理,别让一个文档无限膨胀。

3.3 本地优先与云端同步的平衡

AFFiNE 支持两种使用模式:纯本地模式和云端同步模式。纯本地模式就是所有数据存在浏览器或本地客户端里,不经过任何服务器。云端同步模式则需要自己部署一个 AFFiNE 的服务端,或者用他们提供的托管服务。

我两种都试过。纯本地模式适合个人使用,数据完全在自己手里,但多设备同步就没办法了。云端同步模式需要自己部署服务端,我用 Docker 在一台小服务器上跑了一个,配置不算复杂,但要注意数据备份和版本升级的问题。

这里有个细节值得说:AFFiNE 的云端同步不是简单的“把本地数据上传到服务器”,而是服务器也维护一份 CRDT 文档,各端和服务器做双向同步。这意味着服务器本身也是一个“客户端”,只是它不渲染界面。这种设计的好处是同步逻辑统一,坏处是服务器需要一定的计算资源来处理 CRDT 合并。

4. 从零开始部署 AFFiNE 的完整实操流程

4.1 环境准备与依赖检查

我选择用 Docker 部署服务端,这是最省事的方式。先确认服务器上装了 Docker 和 Docker Compose。我用的是 Ubuntu 22.04,Docker 版本 24.x,Compose 版本 v2.x。这些基础环境如果还没装,网上教程很多,这里不展开。

需要准备的资源:

  • 一台能跑 Docker 的服务器,配置不用太高,1 核 2G 内存起步就够个人用
  • 一个域名(可选,但建议有,方便 HTTPS 访问)
  • 如果要用 HTTPS,还需要准备证书,可以用 Let's Encrypt 免费申请

注意:AFFiNE 的服务端对内存有一定要求,如果文档多、协同频繁,建议至少 2G 内存。我一开始用 1G 内存的机器跑,文档多了之后偶尔会卡顿,加到 2G 后就顺畅了。

4.2 Docker 部署服务端的详细步骤

AFFiNE 官方提供了 Docker 镜像,部署命令大致如下。我把它拆成几个步骤来说明:

第一步,创建数据目录和配置文件:

mkdir -p /opt/affine/data cd /opt/affine

第二步,写一个 docker-compose.yml 文件:

version: '3' services: affine: image: ghcr.io/toeverything/affine-graphql:stable container_name: affine restart: unless-stopped ports: - "3010:3010" volumes: - ./data:/root/.affine/storage environment: - AFFINE_SERVER_HOST=你的域名或IP - AFFINE_SERVER_PORT=3010 - AFFINE_SERVER_HTTPS=false

第三步,启动服务:

docker compose up -d

第四步,检查日志确认启动成功:

docker compose logs -f

看到类似“Server started”的日志就说明起来了。然后浏览器访问http://你的服务器IP:3010就能看到界面。

提示:如果要用 HTTPS,建议在前面加一个 Nginx 反向代理,把 443 端口的请求转发到 3010。Nginx 配置里记得加 WebSocket 支持,因为 AFFiNE 的协同同步走的是 WebSocket。

4.3 客户端配置与首次使用

服务端跑起来后,客户端可以用浏览器直接访问,也可以下载桌面客户端。桌面客户端的好处是支持本地文件系统集成,可以把附件存在本地而不是浏览器缓存里。

首次使用时,需要注册一个账号。如果是自己部署的服务端,第一个注册的账号通常就是管理员。注册完成后,可以创建一个工作区(Workspace),然后就可以开始建文档了。

我建议第一次使用时先做几件事:

  1. 在设置里把语言改成中文(如果界面默认是英文)
  2. 检查一下存储路径,确认数据存在你期望的位置
  3. 建一个测试文档,试试文档、白板、表格三种视图的切换
  4. 如果有多台设备,试试同步是否正常

4.4 数据备份与迁移的注意事项

自己部署服务端,数据备份是必须的。AFFiNE 的数据主要存在两个地方:一个是 PostgreSQL 数据库(存元数据和用户信息),一个是文件存储目录(存文档内容和附件)。

备份策略我建议:

  • 数据库每天定时 dump 一次,保留最近 7 天的备份
  • 文件存储目录用 rsync 定期同步到另一台机器或对象存储
  • 升级版本前一定要先备份,因为数据库结构可能变化

迁移的话,把数据库 dump 和文件目录一起搬到新服务器,按同样的方式部署,然后把数据恢复进去就行。注意版本要一致,跨大版本迁移可能会有兼容问题。

5. 实际使用中遇到的坑与排查记录

5.1 同步冲突与数据恢复

我遇到过一次比较严重的问题:两台设备同时编辑同一个文档,其中一台设备在离线状态下改了很多内容,另一台设备也在线改了不少,等离线设备联网同步后,发现部分内容出现了重复块。

排查下来,原因是离线设备在同步前做了本地快照压缩,导致部分操作历史丢失,同步时无法正确合并。解决办法是:尽量不要在长时间离线后直接同步大量修改,可以先导出本地内容,同步后再手动合并。

AFFiNE 有导出功能,支持导出为 Markdown、PDF 等格式。我现在的习惯是,如果要在离线状态下做大量修改,先导出一份备份,心里踏实。

5.2 性能问题的排查思路

前面提到过,文档用久了会变慢。我总结了一个排查流程:

现象可能原因排查方法解决方式
打开文档慢操作历史过多看文档块数量和编辑历史长度整理文档,删除无用块
同步延迟高网络问题或服务器负载高检查服务器 CPU 和内存使用率升级服务器配置或优化网络
白板卡顿块数量过多或浏览器性能不足看白板上的块数量和浏览器内存占用拆分白板,减少单页块数量
搜索慢索引未更新或数据量大检查搜索索引状态重建索引或限制搜索范围

我实测下来,单个文档的块数量控制在 500 以内,体验最好。超过 1000 块之后,编辑和同步都会明显变慢。所以建议把大文档拆成多个小文档,用链接关联起来。

5.3 常见问题速查

  • 问题:Docker 容器启动后无法访问检查端口是否被占用,防火墙是否放行,以及AFFINE_SERVER_HOST是否配置正确。

  • 问题:注册账号后无法登录检查数据库连接是否正常,看服务端日志有没有报错。有时候是数据库迁移没完成导致的。

  • 问题:附件上传失败检查存储目录的权限,确保 Docker 容器有写入权限。另外注意文件大小限制,默认可能有限制,可以在配置里调整。

  • 问题:多设备同步后内容不一致先刷新页面,如果还不一致,检查各设备的网络连接。实在不行,导出内容后重新导入。

  • 问题:升级后数据丢失升级前一定要备份。如果已经丢了,看备份文件是否完整,按备份恢复流程操作。

提示:AFFiNE 的社区比较活跃,遇到问题可以去他们的 GitHub Discussions 搜一下,很多坑别人已经踩过了。提问的时候附上服务端日志和复现步骤,得到回复的概率会高很多。

6. 我对 AFFiNE 的一些个人判断

用了这段时间,我对 AFFiNE 的整体评价是:方向对,完成度在快速提升,但还没到可以无脑推荐给所有人的程度。

如果你是对数据主权有要求、愿意花点时间折腾部署、并且能接受一定不稳定性的用户,AFFiNE 值得一试。它的文档和白板融合设计确实解决了我的一部分痛点,本地优先的架构也让我对数据安全更放心。

但如果你想要一个开箱即用、稳定省心的工具,目前可能还是商业产品更合适。AFFiNE 的迭代速度很快,这意味着功能在不断完善,但也意味着偶尔会遇到 bug 或者 breaking change。

我自己的做法是:把 AFFiNE 作为主力工具之一,但不是唯一工具。重要的、长期保存的内容,我会同时保留一份 Markdown 导出。这样即使工具本身出问题,内容也不会丢。这个习惯我觉得对任何工具都适用,不只是 AFFiNE。

最后分享一个小技巧:AFFiNE 的模板功能挺实用的,可以把自己常用的文档结构存成模板,新建的时候直接套用,省去重复排版的时间。我建了几个常用模板,比如“项目周报”“会议记录”“读书笔记”,用起来效率高不少。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询