1. 从"文档工具"到"数字工作台"的认知转变
第一次接触 AFFiNE 是在一个开源社区的项目推荐帖里,当时标题写的就是"Notion 的下一代开源替代品"。说实话,这类标题我见得太多了,几乎每个季度都会冒出来几个号称要"干掉 Notion"的项目,大部分用不了十分钟就能看出是个半成品。但 AFFiNE 不太一样,它让我在浏览器里连续折腾了将近两个小时,而且过程中不断有"这个设计有意思"的瞬间。
先说清楚它到底是什么。AFFiNE 是一个开源的知识管理与协作平台,核心定位是把文档、白板、表格三种形态融合在同一个页面空间里。你可以把它理解成一个"没有模式切换"的工作台——在 Notion 里你需要先想清楚"我要建一个 Page 还是一个 Database",在 AFFiNE 里你直接开始写,写到一半想画个流程图就画,想拉个表格就拉,所有内容都在同一个画布上自然生长。
这个定位解决的是什么问题?我自己的痛点是:做技术方案评审的时候,需求描述是文档、架构图是白板、排期是表格,这三样东西在传统工具里是割裂的。评审的时候要开三个窗口来回切,改了一处另一处忘了同步。AFFiNE 的 Edgeless 模式让我可以在同一块无限画布上,左边放需求文档,右边画架构图,下面贴排期表,而且文档里的内容可以直接拖到画布上变成卡片。
适合谁来用?如果你是以下几类人,AFFiNE 值得花时间研究:
- 技术团队的技术负责人:需要做方案设计、架构评审、技术文档管理,且对数据自主可控有要求
- 开源项目维护者:需要公开的项目文档、路线图、贡献指南,且希望社区成员能直接参与编辑
- 个人知识管理重度用户:用过 Obsidian、Logseq、Notion,但总觉得少了点什么
- 对数据隐私敏感的用户:希望文档存在自己的服务器上,而不是某家公司的云里
不适合谁?如果你只是需要一个简单的笔记工具,或者团队里大部分人连 Markdown 都不愿意学,那 AFFiNE 的学习曲线可能会让你觉得"何必呢"。它更适合愿意花时间搭建自己工作流的人。
2. AFFiNE 与 Notion 的底层设计差异
2.1 数据模型:Block 树 vs 无限画布
Notion 的底层是一个Block 树结构,每个页面是一棵树,块是节点,数据库是特殊的块集合。这个模型很优雅,但有个根本限制:页面之间是隔离的。你想在页面 A 里引用页面 B 的内容,只能通过链接或者同步块,本质上还是两个独立的空间。
AFFiNE 的数据模型建立在CRDT(无冲突复制数据类型)之上,底层用的是 Yjs 这个库。这意味着什么?意味着多个用户可以同时编辑同一块内容,而且不需要中心服务器来协调冲突。每个客户端维护自己的副本,通过算法自动合并。这个设计带来的直接好处是:离线编辑体验极好,你在地铁上改的内容,到了有网的地方会自动同步,不会出现"冲突了,请选择保留哪个版本"的弹窗。
更关键的是,AFFiNE 把"页面"和"画布"统一了。在 Notion 里,Page 和 Whiteboard 是两种不同的东西;在 AFFiNE 里,每个页面默认就是一个无限画布,你可以用文档模式看它(像 Notion 一样线性排列),也可以切换到 Edgeless 模式(像 Miro 一样自由摆放)。这两种模式看的是同一份数据,只是渲染方式不同。
2.2 本地优先架构的实际意义
"本地优先"这个词这两年很火,但很多人没搞明白它到底意味着什么。我用一个具体场景来说明:
假设你在高铁上,网络时断时续。用 Notion 的话,你每打几个字就要等它转圈保存,网络一断就直接卡住。用 AFFiNE 的话,所有操作先写进本地的 IndexedDB(浏览器环境)或者 SQLite(桌面端),界面立刻响应,同步在后台慢慢做。网络恢复后,本地积累的变更会自动推送到服务器。
这个架构的代价是什么?存储占用会大一些,因为本地要保留完整的数据副本和操作历史。另外,如果你在多台设备上同时编辑同一块内容,虽然 CRDT 能自动合并,但合并结果可能不是你预期的——比如你和同事同时修改了同一段文字的不同部分,合并后可能变成两段并列的文字,需要手动整理。这不是 bug,是分布式系统的固有特性。
2.3 开源协议与商业模式的平衡
AFFiNE 用的是MIT 协议,这意味着你可以自由地使用、修改、分发,甚至拿去做商业产品。但要注意,它同时提供了一个托管服务(AFFiNE Cloud),这部分是收费的。这种"开源核心 + 云服务"的模式在开源圈很常见,好处是核心功能永远免费,坏处是某些高级功能(比如团队权限管理、审计日志)可能只在云版本里提供。
我实际测试下来,自托管版本的功能已经足够完整。文档编辑、白板、表格、多人协作、版本历史这些核心功能都有。缺失的主要是企业级的 SSO、细粒度权限控制、以及一些 AI 辅助功能。对于小团队和个人用户来说,自托管完全够用。
3. 自托管部署的完整实操路径
3.1 环境准备与依赖检查
AFFiNE 的自托管部署方式有好几种,我推荐用Docker Compose,因为它的依赖关系比较复杂,手动装容易漏东西。先确认你的服务器满足以下条件:
| 项目 | 最低要求 | 推荐配置 |
|---|---|---|
| CPU | 2 核 | 4 核以上 |
| 内存 | 4 GB | 8 GB |
| 磁盘 | 20 GB | 50 GB SSD |
| 操作系统 | Ubuntu 20.04+ | Ubuntu 22.04 LTS |
| Docker | 20.10+ | 最新稳定版 |
| Docker Compose | 2.0+ | 最新稳定版 |
检查 Docker 是否安装:
docker --version docker compose version如果没装,用官方脚本安装(Ubuntu/Debian):
curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER执行完最后一条命令后需要重新登录,让用户组变更生效。
3.2 Docker Compose 配置详解
AFFiNE 官方提供了一个docker-compose.yml模板,但直接拿来用有几个地方需要改。我把我实际用的配置贴出来,并解释每个关键参数:
version: '3.8' services: affine: image: ghcr.io/toeverything/affine-graphql:stable container_name: affine restart: unless-stopped ports: - "3010:3010" volumes: - ./data:/root/.affine/storage - ./config:/root/.affine/config environment: - AFFINE_SERVER_HOST=your-domain.com - AFFINE_SERVER_HTTPS=true - AFFINE_SERVER_PORT=3010 - AFFINE_ADMIN_EMAIL=admin@example.com - AFFINE_ADMIN_PASSWORD=your-strong-password - DATABASE_URL=postgresql://affine:password@postgres:5432/affine - REDIS_SERVER_HOST=redis depends_on: - postgres - redis postgres: image: postgres:16-alpine container_name: affine-postgres restart: unless-stopped volumes: - ./postgres-data:/var/lib/postgresql/data environment: - POSTGRES_USER=affine - POSTGRES_PASSWORD=password - POSTGRES_DB=affine redis: image: redis:7-alpine container_name: affine-redis restart: unless-stopped volumes: - ./redis-data:/data几个关键点说明:
AFFINE_SERVER_HOST必须填你实际访问的域名或 IP。如果填错了,前端会加载不出来,控制台会报跨域错误。我一开始填的localhost,结果局域网内其他设备访问不了,改成实际 IP 后正常。
AFFINE_SERVER_HTTPS如果你用了反向代理(Nginx/Caddy)并且配了 SSL 证书,设为true;如果只是内网 HTTP 访问,设为false。这个参数影响前端生成的资源链接协议。
数据持久化一定要把./data和./postgres-data映射到宿主机。我有一次升级镜像时忘了备份,直接docker compose down把数据全清了,好在是测试环境。生产环境务必定期备份这两个目录。
3.3 反向代理与 HTTPS 配置
直接用 IP 加端口访问体验很差,而且很多浏览器 API(比如剪贴板、通知)要求 HTTPS 环境。我用的是 Caddy,配置比 Nginx 简单很多:
affine.your-domain.com { reverse_proxy localhost:3010 encode gzip }Caddy 会自动申请和续期 Let's Encrypt 证书,省心。如果你用 Nginx,配置大概是:
server { listen 443 ssl http2; server_name affine.your-domain.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://localhost:3010; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }注意:WebSocket 的 Upgrade 头必须配置,否则多人协作的实时同步会失效,表现为"别人改了内容我看不到"。
3.4 首次启动与初始化
配置好后,在docker-compose.yml所在目录执行:
docker compose up -d然后查看日志确认启动成功:
docker compose logs -f affine看到类似Server started on port 3010的输出就说明起来了。浏览器访问你的域名,用配置里的管理员邮箱和密码登录。
第一次登录后建议做几件事:
- 修改管理员密码:环境变量里的密码是初始密码,登录后到设置里改掉
- 创建第一个工作区:AFFiNE 用 Workspace 来隔离不同团队的数据
- 测试协作功能:开两个浏览器窗口,用不同账号登录,同时编辑一个页面,看同步是否正常
4. 实际使用中踩过的坑与解决方案
4.1 中文输入法的兼容性问题
这是我在早期版本遇到的最影响体验的问题。在 Edgeless 模式下用中文输入法打字时,候选词框的位置会偏移,有时候直接跑到屏幕外面。原因是画布的坐标变换没有正确传递给输入法框架。
临时解决方案:在文档模式下编辑中文,写完了再切到 Edgeless 模式排版。或者用桌面客户端,桌面端的输入法处理比浏览器端好很多。
长期方案:关注项目的 GitHub Issues,这个问题在 0.14 版本之后有了明显改善,但偶尔还会出现。如果你用的是自托管版本,升级到最新稳定版能解决大部分输入法问题。
4.2 大文档的性能拐点
我测试过一个包含约 5000 个块的文档,在浏览器里滚动开始出现明显卡顿。用 Chrome 的 Performance 面板分析,发现主要耗时在虚拟滚动的重计算上。AFFiNE 的文档模式用了虚拟滚动来优化性能,但当块的高度不固定时(比如有的块是代码块,有的是图片),滚动时的位置计算会很频繁。
实操建议:
- 单个文档的块数量控制在 2000 以内,超过就拆分成多个页面
- 图片尽量用图床链接而不是直接上传,减少块的高度变化
- 如果必须处理大文档,用桌面客户端,内存管理比浏览器好
4.3 自托管版本的邮件通知配置
AFFiNE 支持邮件通知(比如有人提到了你),但自托管版本默认没有配置 SMTP,需要手动加环境变量:
environment: - MAILER_HOST=smtp.example.com - MAILER_PORT=587 - MAILER_USERNAME=your-email@example.com - MAILER_PASSWORD=your-email-password - MAILER_SENDER=notifications@example.com我踩过的坑是:MAILER_SENDER 必须和 MAILER_USERNAME 的域名一致,否则大部分邮件服务商会拒收。比如你用 Gmail 的 SMTP,发件人必须也是 Gmail 地址。
4.4 数据备份与迁移的注意事项
自托管最大的风险就是数据丢失。我现在的备份策略是:
- 每日增量备份:用
rsync同步./data和./postgres-data到另一台机器 - 每周全量备份:用
pg_dump导出数据库,和文件目录一起打包 - 升级前手动快照:每次升级镜像前,先
docker compose down,复制整个目录,再升级
迁移到新服务器时,把备份的目录复制过去,用相同版本的镜像启动,数据就能恢复。注意PostgreSQL 的版本要一致,从 15 升到 16 需要额外的迁移步骤。
5. 从 Notion 迁移到 AFFiNE 的实操策略
5.1 导入 Notion 数据的正确姿势
AFFiNE 支持导入 Notion 的导出文件(Markdown + CSV),但直接导入会有几个问题:
问题一:数据库关系丢失。Notion 的 Relation 和 Rollup 字段在导出时变成纯文本,导入后无法恢复关联。我的做法是:先在 Notion 里把关系字段展开成普通文本,导入后再在 AFFiNE 里手动重建关联。
问题二:图片路径错误。Notion 导出的 Markdown 里图片是相对路径,导入 AFFiNE 后如果不同时上传图片文件夹,图片会显示不出来。正确做法是:导出时选择"包含内容",把 Markdown 文件和图片文件夹一起压缩,然后在 AFFiNE 里导入压缩包。
问题三:嵌套页面层级混乱。Notion 的子页面在导出时变成同级文件,导入后需要手动调整层级。建议分批导入,先导入顶层页面,再逐个导入子页面。
5.2 哪些内容适合迁移,哪些不适合
不是所有 Notion 内容都值得搬到 AFFiNE。我的经验是:
| 内容类型 | 是否迁移 | 原因 |
|---|---|---|
| 技术文档 | 推荐 | AFFiNE 的文档编辑体验更流畅 |
| 项目看板 | 看情况 | AFFiNE 的表格功能还在完善中 |
| 个人日记 | 推荐 | 本地优先架构更适合私密内容 |
| 团队 Wiki | 推荐 | 协作体验好,且数据自主可控 |
| 复杂数据库 | 不推荐 | AFFiNE 的数据库功能不如 Notion 成熟 |
| 公式密集型文档 | 不推荐 | LaTeX 渲染偶尔有问题 |
5.3 迁移后的工作流调整
从 Notion 搬到 AFFiNE 后,有几个习惯需要改:
不要急着建数据库。AFFiNE 的表格更适合做简单的数据展示,复杂的关联查询还是 Notion 强。我的做法是:需要复杂数据库的场景继续用 Notion,日常文档和协作搬到 AFFiNE。
善用 Edgeless 模式做头脑风暴。这是 AFFiNE 相比 Notion 最大的优势。我现在开需求评审会时,直接在 Edgeless 画布上贴便签、画流程图、写结论,会议结束就形成了一份完整的会议记录,不需要再整理。
用本地优先的特性做离线工作。出差前把需要看的文档在桌面端打开一次,数据就缓存到本地了,飞机上也能正常查阅和编辑。
6. 开源项目的参与方式与生态现状
6.1 如何给 AFFiNE 贡献代码
AFFiNE 的代码仓库在 GitHub 上,主要用 TypeScript 和 Rust 开发。如果你想参与贡献,流程大概是:
- Fork 仓库,克隆到本地
- 安装依赖:项目用
pnpm做包管理,需要 Node.js 18+ - 启动开发环境:
pnpm dev会启动前端和后端的热重载 - 找 Issue:新手建议从
good first issue标签开始 - 提交 PR:注意遵循项目的 Commit 规范(Conventional Commits)
我贡献过一个小 bug 修复,从提交到合并大概用了一周。维护者的反馈很及时,但要求也比较严格,代码风格和测试覆盖率都有要求。
6.2 插件系统与扩展可能性
AFFiNE 目前还没有像 Obsidian 那样成熟的插件系统,但底层架构已经预留了扩展点。我了解到的情况是:
- Block 类型可以扩展:你可以注册新的块类型,比如嵌入一个自定义的图表组件
- 编辑器命令可以扩展:通过 Slash 命令注册自定义操作
- 后端 API 可以扩展:GraphQL 接口支持自定义 resolver
不过这些都需要改源码,不是开箱即用的插件机制。如果你有开发能力,可以基于它的 SDK 做一些定制;如果只是普通用户,建议等官方的插件系统上线。
6.3 社区资源与学习路径
我整理了几个有用的资源:
- 官方文档:docs.affine.pro,有完整的部署指南和 API 文档
- GitHub Discussions:遇到问题先在这里搜,大部分常见问题都有讨论
- Discord 社区:实时交流,维护者经常在线
- B站和 YouTube:搜"AFFiNE 教程",有几个 UP 主做了很详细的使用指南
学习路径建议:先用托管版本熟悉基本操作,然后自托管部署,最后根据需求决定是否深入源码。不要一上来就折腾部署,容易在环境问题上卡住而放弃。
7. 我对 AFFiNE 的真实评价与使用建议
用了大概三个月,AFFiNE 已经成为我日常工作中不可或缺的工具。但它不是完美的,我来说说真实感受。
让我惊喜的地方:Edgeless 模式彻底改变了我的会议记录方式,以前开会要一边听一边打字,现在直接画图贴便签,效率高很多。本地优先架构在移动场景下体验极好,高铁上、飞机上都能正常编辑。开源协议宽松,我可以放心地把公司内部文档放上去,不用担心数据被第三方获取。
让我头疼的地方:中文输入法的兼容性虽然改善了但还没完美,偶尔会抽风。大文档的性能还有优化空间,超过 3000 个块就开始卡。移动端 App 的功能比桌面端少很多,只能做简单的查看和编辑。
给新用户的建议:不要试图一次性把所有东西都搬过来,先从一个具体的场景开始用,比如"用 Edgeless 做会议记录"或者"用文档模式写技术方案"。用顺了再逐步扩展。自托管部署建议用 Docker Compose,不要手动装依赖,坑太多。数据备份一定要做,而且要做异机备份,不要存在同一台服务器上。
最后分享一个我常用的技巧:在 Edgeless 模式下,用Ctrl/Cmd + 拖拽可以框选多个元素,然后按Ctrl/Cmd + G编组。编组后的元素可以整体移动和缩放,做架构图的时候特别方便。这个操作在官方文档里没写,是我自己试出来的。