ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AFFiNE 自托管部署与 Notion 迁移实战:开源知识管理平台深度解析

AFFiNE 自托管部署与 Notion 迁移实战:开源知识管理平台深度解析 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因为它的依赖关系比较复杂手动装容易漏东西。先确认你的服务器满足以下条件项目最低要求推荐配置CPU2 核4 核以上内存4 GB8 GB磁盘20 GB50 GB SSD操作系统Ubuntu 20.04Ubuntu 22.04 LTSDocker20.10最新稳定版Docker Compose2.0最新稳定版检查 Docker 是否安装docker --version docker compose version如果没装用官方脚本安装Ubuntu/Debiancurl -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_HOSTyour-domain.com - AFFINE_SERVER_HTTPStrue - AFFINE_SERVER_PORT3010 - AFFINE_ADMIN_EMAILadminexample.com - AFFINE_ADMIN_PASSWORDyour-strong-password - DATABASE_URLpostgresql://affine:passwordpostgres:5432/affine - REDIS_SERVER_HOSTredis 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_USERaffine - POSTGRES_PASSWORDpassword - POSTGRES_DBaffine 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 会自动申请和续期 Lets 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_HOSTsmtp.example.com - MAILER_PORT587 - MAILER_USERNAMEyour-emailexample.com - MAILER_PASSWORDyour-email-password - MAILER_SENDERnotificationsexample.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编组。编组后的元素可以整体移动和缩放做架构图的时候特别方便。这个操作在官方文档里没写是我自己试出来的。
返回列表