资讯详情

资讯详情

浏览器扩展+本地服务:构建个人知识管理插件的完整实践

前阵子我把自己的碎片化知识整理工具全部重写了一遍最终沉淀成一套以浏览器扩展为基础的知识工作插件集合名字就叫 knowledge-work-plugins。这名字听起来很大但拆开看就是一句话凡是能帮你把“读过的内容”变成“用得上的知识”的小工具都可以装进这套插件体系里。我对此前的工具很不满收藏夹里躺着两千多条网页真正打开过的不超过五十条网页高亮存了一堆最后根本导不出来看了几十篇资料写文章想引用时却要重新翻链接。所以这次做 knowledge-work-plugins 时我给自己定了几个硬性目标——轻量、本地优先、可扩展、能跟 Markdown 工作流无缝衔接。这篇文章不聊宏大的知识管理理念就讲讲我实际怎么设计、怎么实现、怎么排查坑。如果你也在做知识管理工具或者正被“收藏从未停止阅读从未开始”困扰这篇应该能给你一些能直接拿来用的思路。1. 先想清楚知识工作流到底卡在哪1.1 知识工作流的真实瓶颈很多人以为知识管理的核心问题是“存储”其实不是。存储工具已经很多了真正卡住工作流的是“输入、理解、提取、复现”之间的断层。我把自己过去半年的操作习惯从头到尾捋了一遍发现知识工作者最常见的动作根本不是“整理笔记”而是三个高频小动作在网页里划一段有用的话把整篇文章收藏起来以及过几天想用的时候回头找原文。这三个动作看起来简单但现有工具把它们拆成了三个独立场景浏览器负责阅读笔记软件负责记录收藏夹负责囤积。结果就是信息在三个地方各存一份互相之间没有任何关联。更让人崩溃的是“上下文切换”的成本。我写过一篇长文中间引用了五个来源。每次想要确认某句话的出处都要从编辑器切到浏览器重新搜索、打开网页、找到段落。这个过程来回一趟至少一两分钟思路早就断了。我统计过如果一天写两千字光是这种“溯源”动作就能打断十几次。所以我在动手前给自己做了一次“信息处理日志”把一周内所有“看到内容 - 决定要不要留下”的瞬间都记下来。结论很清晰超过60%的知识处理动作发生在浏览器里而且集中在“选中文本”和“右击菜单”这两个入口。这也是整个项目定位的起点——不是做一个大而全的App而是做一组能嵌入现有工作流的轻量插件让保存、批注、溯源变成“顺手就能做”的事而不是需要额外打开一个软件的重操作。1.2 设计原则本地优先和插拔式模块我最开始试过把功能全写在一个大插件里结果更新频繁、权限膨胀连我自己都受不了。后来改变思路拆成几个独立模块页面剪藏、划线批注、引用收集、待办弹窗、间隔复习。每个模块对应一个插件能力也可以合并为一个扩展运行通过统一的配置文件控制开关。这个“插拔式”设计的核心好处是每个模块可以独立更新、独立开关不会因为某个功能不稳定而影响整个知识库。比如引用收集模块偶尔抽风页面剪藏和批注还能正常用。权限也能做到最小化——只用剪藏的人不需要申请“读取所有网站数据”的权限。设计上我坚持了几条原则本地优先数据始终先落在本地文件或本地数据库里不上传任何云端。只有在你明确配置了自建同步服务时才会有数据从本机出去。Markdown作为交换格式剪藏和批注都能一键导出为 Markdown和主流笔记软件、代码编辑器、纯文本工具都能打通。权限最小化每个模块只申请它真正需要的权限避免“安装一个插件却拿到整个浏览器访问权”的尴尬。这既是为了用户安全也是为了通过应用商店审核时少一点麻烦。键盘优先知识工作者长时间打字快捷键是所有高频操作的默认入口。能用键盘完成的动作绝不强迫你点鼠标。1.3 适合谁用三类典型用户这套东西并不是为所有人设计的。我做出来以后发现最适合的是这三类人第一类是“内容研究者”。他们需要经常阅读大量网页资料并要把关键段落提取到自己的资料库里最终产出文章、报告或课程内容。对他们来说划选保存、引用溯源是刚需剪藏插件就是他们的第二双手。第二类是“知识管理重度用户”。他们已经有自己的笔记库、标签体系和回顾习惯缺的不是存储空间而是从浏览器到笔记库的“管道”。这套插件能直接入他们已有的 Markdown 或数据库工作流不需要迁移。第三类是“信息囤积症患者”。他们收藏了一堆内容但很少回看。他们需要的是“低摩擦捕获”和“间隔提醒”先解决“存下来没负担”再慢慢培养回顾习惯。我用简化版间隔复习模块正好能接住这个需求。如果你属于这三类中的任何一类下面这几章的内容可以直接照着做。2. 技术选型为什么是浏览器扩展而不是桌面App2.1 浏览器扩展 本地服务的组合逻辑在动手前我在“桌面App”和“浏览器扩展”之间犹豫了很久。桌面App开发周期长要处理窗口、系统托盘、开机启动一堆事而且每次想保存网页内容都得从浏览器切到另一个窗口。浏览器扩展虽然开发简单但有沙箱限制不能直接读写本地文件尤其是现代浏览器扩展权限管理非常严格。最后我选择了“浏览器扩展 本地服务”的组合扩展负责接触页面、获取选中文本和网页元数据本地服务负责处理数据落盘。两者之间通过本地 HTTP 接口传递 JSON。具体数据流是这样的页面划选文字 - 点击右键菜单“保存到知识库” - 扩展把文本和元数据打包成JSON - 通过本地 HTTP 请求发给本机服务 - 服务接收后校验内容追加写入指定目录的 Markdown 文件 - 同时把网页快照存一份到附件目录。为什么要把数据落到本地服务而不是直接存在扩展的 storage 里因为扩展的存储空间有限也不适合当长期档案库。浏览器扩展随时可能因为卸载、清缓存、更新异常而丢失数据本地文件则是可控的可以用版本管理工具做历史记录也可以直接用文件管理器浏览、备份。当然如果你不需要本地文件也可以直接把数据存入扩展的 IndexedDB后续再手动导出。这两种模式我都实现了。第一种适合“知识库在主工作流里”的人第二种适合“先攒着以后统一整理”的人。你完全可以根据自己的习惯选择数据落点。2.2 关键API与技术点写浏览器知识插件绕不开下面几个技术点我把它们拆开讲清楚。首先是推荐使用 Manifest V3 规范。这是现代浏览器扩展的标准写法。它有一个重要的权限模型变化扩展必须在 manifest.json 里显式声明要用的权限比如 activeTab、scripting、storage、contextMenus。这里尤其要注意不在 manifest 里声明对应接口就用不了。网上很多老教程是 Manifest V2 的字段名和权限策略都不一样直接套用会踩坑。其次是 content_scripts 与页面交互。内容脚本是唯一能在网页上下文里操作 DOM 的扩展部件。但你不能想当然地以为内容脚本会在所有页面百分百运行有的页面有 iframe 嵌套有的页面是 PDF 查看器有的页面是浏览器内置页面这些都是例外。划选文本的经典做法是利用 Selection APIfunction getSelectedText() { const selection window.getSelection(); if (!selection || selection.rangeCount 0) return ; return selection.toString().trim(); }然后监听 mouseup 或 keyup 事件判断是否有选中文本。再次是右键菜单 contextMenus。这是所有知识插件里体验最好的入口。你可以给“选中文本”的上下文注册一个菜单项用户右键就能触发保存。它的性能和稳定性比自定义浮动按钮好得多因为右键菜单是浏览器原生组件不依赖页面 DOM 渲染。接着是 chrome.storage.session。这个 API 用于临时状态比如当前正在处理的标签页信息。它比全局变量靠谱因为扩展的 background 在 Manifest V3 里是 Service Worker可能随时被浏览器回收全局变量会丢失而 storage.session 能存住。对于大文本和高亮坐标用 IndexedDB。localStorage 不适合存结构化大对象而且每个域名有独立空间同步和导出都不方便。IndexedDB 可以存大文本并且能用简单的增删改查接口操作。最后一个技术层面是 host_permissions 的使用时机。如果扩展需要主动往某些站点注入脚本或读取页面完整数据就要通过 host_permissions 声明目标站点的匹配规则。但申请过多会让用户在安装时看到“读取和更改所有网站数据”的红色警告对信任度影响很大。所以我的策略是默认不申请全部站点只在功能真正需要时才让用户手动授权。2.3 数据格式设计一次积累处处可用知识类插件最容易被忽略的是数据格式设计。很多剪藏插件存的是“网页全文”结果导出后一堆 HTML 标签根本没法用还有的只存一个标题和链接过了没多久链接失效内容就彻底丢了。我设计的统一数据条目结构是这样的{ id: a1b2c3d4e5f6, type: highlight, source: { url: https://example.com/some-article, title: 某篇文章标题 }, content: { text: 用户划选的原文, excerpt: 上下文摘录 }, meta: { created_at: 2025-01-01T10:00:0008:00, tags: [阅读, 插件开发] } }这个结构有几个好处不依赖特定工具。导出的 JSON 可以转 Markdown、CSV甚至直接导入数据库。保留来源 URL。引用溯源时这个字段能救命。字段命名直观。就算某一天我需要迁移到新的笔记软件数据也能无损转换。type 字段支持后续扩展。高亮、批注、待办、参考文献都可以共用同一个基础结构。Markdown 导出模板也很简单我用一个很小的模板替换函数就完成了原文{{content.text}} 出处 {{source.title}} 时间{{meta.created_at}} 标签{{meta.tags}}关键词是“统一”。无论如何保存最终导出的内容都遵循同一种格式。这样以后不管插件前端怎么改数据层永远是稳定的。我在实际写作里最常做的动作就是把剪藏的 Markdown 段落直接拖进文稿然后基于出处链接做引用整理整个过程不到十秒。2.4 浏览器扩展与桌面App选型对照如果你也在纠结用哪种形式我把我评估时用的对照表放出来参考。维度浏览器扩展桌面App与浏览器的距离原生贴近支持划选、右键、快捷键需要切换窗口开发成本中等用 manifest 规范即可较高要处理窗口、生命周期等数据落盘能力受限需配合本地服务可直接读写任意目录发布与更新走应用商店审核走独立分发渠道安全权限感知用户安装时会看到权限警告首次运行时的系统授权适合场景轻量捕获、网页批注大规模知识库管理、深度加工从表格能看出来没有哪个方案绝对更好关键是你要做的是“捕获”还是“管理”。如果你想解决的是“看到好东西想顺手存下来”浏览器扩展优势巨大如果你需要的是本地多文件批量处理、全文检索、复杂打标桌面App更适合。我在 knowledge-work-plugins 里选择了前者因为我的主要瓶颈在输入侧。3. 从零手写一个能用的知识剪藏插件3.1 最小可用版本的四步搭建这部分写给没写过浏览器扩展的人老手可以直接跳到 3.2。我当初也是从官方文档起步的整个过程就四步。第一步创建项目目录写 manifest.json。这是扩展的门面也是最容易出问题的地方。{ manifest_version: 3, name: knowledge-work-plugins, version: 0.4.0, permissions: [activeTab, scripting, storage, contextMenus], background: { service_worker: background.js }, content_scripts: [ { matches: [all_urls], js: [content.js], run_at: document_idle } ], action: { default_popup: popup.html } }这里的 permissions 四件套是有讲究的activeTab 是为了在用户点击扩展图标时访问当前标签页scripting 是为了能动态注入脚本storage 是存取设置和临时状态contextMenus 是注册右键菜单。我没有申请所有站点的主机权限而是让用户按需触发这样安装时看到的权限列表会干净很多。第二步写 background.js注册右键菜单。chrome.runtime.onInstalled.addListener(() { chrome.contextMenus.create({ id: save-selection, title: 保存到知识库, contexts: [selection] }); }); chrome.contextMenus.onClicked.addListener((info, tab) { if (info.menuItemId save-selection) { chrome.tabs.sendMessage(tab.id, { action: SAVE_SELECTION }); } });这里的关键点是 contextMenus.create 一定要放在 onInstalled 事件里。我第一次写的时候把它放在顶层结果每次 Service Worker 被唤醒都会重新注册最终菜单里出现了好几个“保存到知识库”。这个问题非常隐蔽等你在右键菜单里看到三四个相同选项时才意识到是重复注册了。第三步content.js 接收消息并发送数据。chrome.runtime.onMessage.addListener((msg, sender, sendResponse) { if (msg.action SAVE_SELECTION) { const text getSelectedText(); if (text) { sendResponse({ text, url: location.href, title: document.title }); } else { sendResponse({ error: no selection }); } } });注意sendResponse 是同步返回如果你要在收到消息后做异步操作比如去读存储或发请求需要在 return true 之后保持通道打开。这一步忘了消息会直接丢失控制台却看不到任何报错。第四步写一个极简 popup.html 设置页能显示当前各模块开关状态和快捷键提示即可。这不是必须的但值得有。因为插件能力越多越需要一眼看到“当前哪个模块是开的”。我后来还在设置页里加了一个“打开本地知识库目录”的按钮点击后通过本地服务调用系统文件管理器直接就能看到刚才剪藏的内容效果非常直观。四步走完你就拥有一个能在任意网页划词、右键保存的扩展了。剩下的是把它连到本地服务或 IndexedDB形成完整闭环。3.2 本地服务对接让剪藏直接变成Markdown我写了大约一百二十行本地服务脚本启动后监听本机回环地址的固定端口接收 POST 请求写入文件。不和外部网络通信也不做任何鉴权因为只在自己电脑上跑。核心代码长这样const http require(http); const fs require(fs); const path require(path); const crypto require(crypto); const KNOWLEDGE_DIR path.join(process.env.HOME, knowledge-base, inbox); function slugify(url, title) { const hash crypto.createHash(sha256).update(url).digest(hex).slice(0, 8); const base title.replace(/[^\w\u4e00-\u9fa5\-]/g, _).slice(0, 60); return ${base}-${hash}.md; } http.createServer((req, res) { if (req.method POST req.url /save) { let body ; req.on(data, (chunk) body chunk); req.on(end, () { const data JSON.parse(body); const filename slugify(data.source.url, data.source.title); const md [ 原文${data.content.text}, 出处[${data.source.title}](${data.source.url}), 时间${data.meta.created_at}, 标签${(data.meta.tags || []).join(, )}, , data.content.excerpt || ].join(\n); fs.writeFileSync(path.join(KNOWLEDGE_DIR, filename), md, utf8); res.writeHead(200, { Content-Type: application/json }); res.end(JSON.stringify({ ok: true })); }); } else { res.writeHead(404); res.end(); } }).listen(53123, 127.0.0.1);这里有几个关键设计值得展开讲。文件名里加了 URL 哈希是为了避免两篇同标题文章互相覆盖。只取前8位十六进制哈希一共有32比特空间个人知识库规模下碰撞概率可以忽略。标题放在前面、哈希放后面是为了文件管理器里一眼能认出是哪篇文章。如果你的使用习惯是按来源站点分类也可以改用“站点名-标题-哈希.md”的命名规则。写入文件时强制使用 utf8 编码是为了防止在部分操作系统下中文名或内容出现乱码。这个坑在 Windows 上尤其常见我吃过不少亏。顺便说一个经验如果你打算长期使用这套东西建议把本地服务做成开机自启。不然每次用完电脑重启都得记得手动把它跑起来否则扩展发来的数据没人接收会一直堆积在发送队列里。我用系统自带的任务计划来托管配置了失败自动重启之后就再也没管过它。扩展那边发请求的方式很简单。在 background.js 里直接向http://127.0.0.1:53123/save发 POST。但这里有一个扩展开发的老问题扩展的 background 发跨域请求会受策略限制需要在 manifest.json 里声明host_permissions: [http://127.0.0.1:53123/*]。这是最直接的方案。如果你不想申请这个权限就只能走 native messaging但那个方案的开发和调试成本会高很多对个人项目来说不划算。3.3 间隔复习模块让知识真的“用起来”收集知识只是第一步。如果只存不看那跟把文件塞进硬盘角落没有区别。我额外写了一个间隔复习模块每天固定时间在扩展弹窗里展示之前保存的知识卡片根据你当天的记忆反馈调整下次出现时间。算法不复杂就是简化版的 SM-2初次保存后优先级计数为 0。回答“还记得”后优先级计数加 1并推入队列尾部。回答“忘记了”后优先级计数归零并且当天再次插入队列保证你在一天内至少再看一次。用伪代码描述是这样的function review(card, isRemembered) { if (isRemembered) { card.priority; queue.push(card); } else { card.priority 0; queue.unshift(card); } }这套东西虽然不够智能但已经把“回顾”这个动作强制放进了工作流。我用了一个多月后对收集内容的记忆深度明显比从前更好因为每天都会被动看到那些陈旧的笔记。如果你不想写复习算法也可以用浏览器自带书签的随机打开功能或者笔记软件的“随机回顾”能力来替代。核心思路都一样把“回顾”变成一种低成本的被动行为而不是需要靠意志力完成的额外任务。3.4 用版本管理工具保护知识库既然数据最终是本地文件那自然能享受版本管理的红利。我在知识库目录里初始化了版本管理仓库每次本地服务收到新剪藏保存文件后顺带做一次提交。命令很简单cd ~/knowledge-base git add -A git commit -m add: 标题 --quiet这样做的收益非常大。即使某一天我误删了某个文件或者某篇剪藏内容被错误覆写都可以从历史记录里找回来。更重要的是我可以随时回滚到一周前的索引状态对比哪些内容发生了变化。要注意的是提交操作是异步的不要在本地服务的请求回调里同步执行否则阻塞的话会让剪藏响应变慢。我当时的做法是把提交命令丢给系统异步执行做一次延后提交。你也可以用简单的防抖策略比如五分钟内多条剪藏合并成一次提交减少仓库里的无用历史点数。4. 踩坑实录权限、去重、快捷键与数据迁移4.1 内容脚本不生效一半是权限问题一半是时序问题这是我在开发过程中遇到最多的问题。内容脚本没在目标页面执行通常有三个原因manifest.json 的 matches 没有适配当前页面或者页面是特殊格式比如 PDF 查看嵌套页面。扩展安装后需要刷新页面内容脚本才会注入到已经打开的标签页。这个问题几乎每个初次使用扩展的人都会遇到——装了插件却看不到效果一刷新反而好了。某些页面明确拒绝注入扩展脚本比如浏览器内置页面或应用商店页面这些页面不受普通扩展控制。排查方法其实不复杂。在目标页面打开开发者工具看看控制台里chrome.runtime是否存在。如果不存在说明脚本没有注入。如果注入失败了检查扩展详情页里的“查看 Service Worker 日志”很多报错信息都在那里。另外一个容易被忽略的问题如果你只申请了 activeTab 权限那么用户没有点击扩展图标之前内容脚本实际上没有访问当前页面数据的权限。这时你通过右键菜单触发消息目标页面的监听器根本收不到。解决办法是在 background 里临时调用 scripting API 注入一次内容脚本或者直接在 manifest 里声明对应站点的主机权限。这个要根据你的隐私取舍来定。我的做法是默认申请activeTab和scripting不申请全局主机权限如果用户需要对特定站点使用完整页面分析功能再在设置页里手动添加一次性的站点授权。这样一来日常使用不受影响权限警告也少很多。4.2 划词保存重复防抖和哈希去重前文提到过mouseup 事件连续触发会导致同一次划选被保存多遍。我刚开始调试的时候测试一篇文章结果知识库里出现了三份完全一样的高亮记录。后来在内容脚本里加了防抖和内容哈希去重let lastText ; let lastTime 0; document.addEventListener(mouseup, () { const now Date.now(); const text getSelectedText(); if (text lastText || now - lastTime 800) return; lastText text; lastTime now; chrome.runtime.sendMessage({ type: TEXT_SELECTED, text }); });防抖解决的是“在短时间内的重复触发”哈希去重解决的是“同一次划选被不同事件触发后的内容一致性”。这两者不能互相替代。我建议在客户端和保存端都做一次去重——前端防抖可以减少无效请求后端去重可以兜底防止因为扩展更新或消息重发造成重复写入。4.3 快捷键冲突怎么办浏览器扩展的快捷键很容易和系统快捷键或网页内建的快捷键撞车。我的策略是所有插件动作都同时提供右键菜单和可配置快捷键不强行给快捷键设置默认全局键只在扩展内部用一个比较冷门的组合比如 AltShiftS并允许用户在扩展设置页里修改。另外不要把快捷键监听直接写在内容脚本里。内容脚本只能感知页面内的键盘事件不能监听扩展级别的命令。想处理全局快捷键必须用 commands APIchrome.commands.onCommand.addListener((command) { if (command save-selection) { /* 触发保存 */ } });然后在 manifest.json 里注册命令commands: { save-selection: { suggested_key: { default: AltShiftS }, description: 保存选中内容 } }这样设置之后只要扩展在后台运行你在任意页面按下这个组合键扩展都能收到命令。如果不生效最常见的原因是浏览器强制保留了某些组合键需要在扩展管理页里手工重新指定。4.4 存储同步冲突与数据迁移有一段时间我用扩展自带的 sync 存储同步设置结果经常出现数据冲突。后来想明白了sync 存储适合存小配置不适合存大数据而且同步机制并不可靠多个设备同时写很容易丢字段。我把方案改成了设置用 sync 存储同步真正的数据用本地 IndexedDB 或者文件系统索引文件交给版本管理工具处理。这样划分之后冲突几乎消失了。如果你已经有旧格式数据要迁移迁移脚本的核心就是两条保持字段映射稳定以及小心字符编码问题。我在迁移时写过一个读取旧目录、生成新 JSON 的脚本跑了两次之后发现写入的文件在部分系统上是乱码最后检查发现是文件系统默认编码不一致。统一用 utf8 写入问题就消失了。迁移过程中不要覆盖原始数据。先输出到迁移目录比对数量、抽查内容无误后再切换正式目录。别嫌麻烦一次误删就能让你后悔。4.5 扩展权限审核要注意什么如果你打算把插件发布到应用商店权限说明是审核的重点。我的经验是把每项权限的用途写在开发者后台的说明栏里尽量用大白话解释。比如“使用剪贴板权限是为了复制选中文本到知识库”“读取收藏夹是为了自动合并网址收藏项”。越具体越容易通过模板化的泛泛说明反而容易触发人工审核。另外要小心不要申请过多权限。如果功能只需要 activeTab就不要去申请全局站点权限。申请越多审核越慢安装转化率越低这三点都对你没好处。最好的策略是“按需触发”——用户第一次用到某个功能时再请求对应权限。4.6 常见问题速查表现象可能原因解决办法右键菜单没有“保存到知识库”contextMenus 注册时机不对把注册逻辑移入 onInstalled 事件点击保存无反应activeTab 权限限制目标页面无内容脚本用 scripting API 临时注入脚本保存内容变成乱码文件写入未指定 utf8写入时显式指定 utf8 编码快捷键无效与系统快捷键冲突在扩展管理页手工修改快捷键多次保存同一句话监听事件重复触发加防抖和哈希去重本地服务启动后过几天失效端口被占用或进程被杀用任务计划或托管工具保活扩展更新后保存规则变了数据格式不兼容先做数据迁移再更新扩展这张表我贴在开发文档最前面每次版本迭代前先对照一遍能省很多排查时间。5. 这套插件还能怎么长5.1 可扩展的插件接口设计knowledge-work-plugins 走到现在已经不只是一个剪藏插件而是一套带接口的知识工作流水线。我留了几个扩展口第一个是 Webhook 输出。除了把内容写入本地 Markdown还可以把新保存的数据以 JSON 形式推送到任意支持 Webhook 的服务比如自建看板、通知机器人、任务管理工具。这样保存一条高亮就能自动触发一个任务草稿或日程提醒。第二个是全文检索。本地 Markdown 积累到几千条以后靠文件管理器翻目录肯定不现实。我打算加入一个轻量级检索组件基于本地索引实现“按关键词、按来源、按时间”的组合查询。目前已经在测试核心思路是用倒排索引把关键词映射到文件路径。第三个是双链引用。在保存剪藏时允许多选已有笔记作为关联目标导出时自动在知识库的两个文件里互相写入链接。这一步能真正把离散的知识点连成网络但实现成本比前两个高一些。我目前先记录关联关系在 JSON 的related_ids字段里导出时才渲染。这些扩展口都是基于最初那个统一数据格式设计的。因为数据结构稳定后面加什么功能都只是在现有字段上做组合不需要回头改历史数据。5.2 个人使用后的几条实在建议用这套插件大半年最后分享几个非常有体感的建议。第一不要迷信功能数量。我做砍掉的需求比做掉的功能多得多。最开始我还想做截图批注、思维导图导出、语音转文字保存后来发现这些都不是我的高频动作砍掉以后反而更清爽。真正高频的就是划选、保存、溯源、回顾把这四个做透已经覆盖了80%的需求。第二数据格式真的比功能重要。换过好几款知识工具之后我最大的感受是功能可以慢慢补数据一旦被格式锁死迁移成本极高。所以在第一步就定好 Markdown 和 JSON 双格式是我整个项目里最正确的决定。第三别把权限安全意识放在最后。扩展一旦申请了“读取所有网站数据”你自己可能无所谓但如果你未来想分享出去用户对权限的警惕性会非常高。宁可多花一点时间做权限最小化也不要图省事一开到底。第四每天花三分钟回顾一次比周末整理四个小时更有用。这个道理其实早就知道但只有把回顾做成“打开浏览器就能看到”的被动行为之后我才真正做到。知识工作靠的从来不是收集速度而是提取效率。这套项目后续我还在继续打磨但核心框架已经稳定。如果你也想做一套自己的知识工作插件我的建议是先记录自己一周的信息处理动作找到那三个最常做的小事然后只做这三个小事的插件。小步快跑远比一开始就搭建一个完美系统靠谱。慢慢地它会跟着你的知识结构一起成长。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →