1. 这不是博客,而是一份程序员的思维手账
“Programming.log”——光看这个名字,你可能以为是个技术博客、个人网站,或者某个开源项目文档站。但其实它更接近于一个程序员写给自己的 思维日志本 。它不追求流量,不迎合算法,不堆砌标题党;它的首页没有导航栏,没有评论区,甚至没有“关于我”页面。它只有一行朴素的说明:“a place to keep my thoughts on programming”,直译过来就是: 一个存放我对编程思考的地方 。
这个词组里藏着三个关键锚点:
log(日志)
、
thoughts(思考)
、
programming(编程)
。它不是代码仓库的 README,不是 Stack Overflow 的问答帖,也不是 Medium 上带封面图的长文。它是一种低摩擦、高密度、强私密性的认知沉淀方式——就像工程师在调试时随手记下的断点观察,像架构师在白板会议后速写的决策草图,像资深开发者深夜重构完一段逻辑后,在终端里敲下的那行
git commit -m "refactor: finally grokked the state machine"
后,顺手在本地 Markdown 文件里补上的两百字反思。
我从 2016 年开始实践这种形式,最初只是用 Sublime Text 打开一个
notes.md
,后来迁移到 Obsidian,再后来自己搭了个极简静态站点,目录结构永远是
/2024/03/15-why-i-stopped-using-async-await-for-this-case.md
。它服务的对象非常明确:
三年前的我、三个月前的我、以及明天早上八点刚被一个诡异竞态 bug 唤醒的我
。它不面向读者,却意外地成为我知识复利最稳定的来源——那些当时写得磕磕绊绊的困惑,半年后回头看,往往已自然演化成一套可复用的判断模式;那些曾让我反复推翻重写的接口设计,如今成了团队新成员入职时的第一份阅读材料。
这类日志的价值,恰恰在于它的“非公开性”和“非完成态”。它允许你写下“我还不懂 React Server Components 的 hydration 边界到底在哪”,而不是硬凑一篇“五分钟搞懂 RSC”的伪教程;它容许你记录“今天花三小时调通了 WebAssembly 模块加载,但根本原因其实是 nginx 缺少
application/wasm
MIME 类型”,而不是包装成“WebAssembly 生产落地全指南”。它不生产内容,它驯服混乱;它不输出答案,它标记问题坐标。如果你正被“写不出高质量技术文章”困扰,或者总在面试时说不清自己做过什么——很可能缺的不是表达能力,而是一份持续运转的 Programming.log。
2. 日志系统的设计哲学:为什么不用现成博客平台?
2.1 核心矛盾:表达欲 vs. 思考欲
绝大多数程序员建站的第一反应是:用 Hexo / Hugo / Next.js 搭个博客,配好 Algolia 搜索、Gitalk 评论、Valine 留言,再接个 RSS 订阅。这很合理——毕竟我们习惯把“能运行”当作第一目标。但 Programming.log 的底层目标完全不同:它要最小化 发布成本 ,最大化 回溯价值 ,并彻底剔除 外部反馈干扰 。
我试过把日志同步到 Medium,结果两周后就停更了。原因很实在:每次写完,平台强制弹出“添加封面图”“选择标签”“是否推送至 Newsletter”三连问;更致命的是,一旦发布,就会收到同事的点赞和“写得真好”的评论——这些正向反馈本该令人愉悦,但在思考沉淀阶段却成了认知负担。我的大脑立刻从“这个状态管理方案为什么在 SSR 下失效”切换到“别人会怎么评价我这段分析”,原始思考的线程被强行中断。这不是写作障碍,而是 注意力主权被平台机制劫持 。
提示:真正的思考日志不需要“发布”动作。它应该像你在 IDE 里新建一个
scratch.ts文件那样自然——双击打开,敲下第一行,保存即完成。任何需要“确认”“审核”“分享”的环节,都在悄悄提高思考的启动门槛。
2.2 技术选型的底层逻辑:静态优先,零依赖,纯文本
Programming.log 的技术栈必须满足三个硬约束:
- 离线可用 :地铁通勤、飞机上、咖啡馆 Wi-Fi 不稳定时,仍能随时打开编辑;
- 格式永生 :十年后用任意文本编辑器都能打开、搜索、修改,不依赖特定渲染引擎;
- 迁移自由 :今天用 Obsidian,明天换 Logseq,后天想导出为 PDF 归档,都不应丢失语义结构。
这就直接排除了所有数据库驱动的 CMS(WordPress、Ghost)、所有云同步笔记(Notion、Bear),甚至排除了部分本地应用(如早期版本的 OneNote)。最终落定在 纯 Markdown 文件 + 静态站点生成器 的组合,不是因为它多先进,而是因为它的“笨”恰好匹配需求:
-
Markdown 是程序员的母语:
#表示标题,-表示列表,``` 表示代码块——无需学习新语法,所见即所得; -
文件系统即数据库:按日期命名(
2024-03-15.md)、按主题建文件夹(/concurrency/、/type-systems/),天然支持grep -r "monad" ./全局搜索; -
静态生成器只做一件事:把
.md转成.html,不掺杂运行时逻辑,不引入第三方 SDK,不收集用户行为。
我对比过 Jekyll、Hugo、Zola 和自研脚本。最终选择 Zola,原因很务实:编译速度比 Hugo 快 40%,配置文件用 TOML(比 YAML 更抗缩进错误),且原生支持
taxonomies
(分类)和
search
(前端搜索)——后者意味着用户在生成的 HTML 页面里,能直接用 Ctrl+F 搜索全文,而无需部署 Algolia 这类外部服务。
注意:不要陷入“工具军备竞赛”。我见过有人为日志系统写了 200 行 Webpack 配置,只为实现“点击标题自动复制链接”。这种复杂度已经背叛了日志的初衷。记住:你的目标是记录思考,不是开发一个 CMS。
2.3 内容结构的反常识设计:拒绝分类法,拥抱时间戳
主流博客都强调“分类”和“标签”:前端、后端、DevOps、AI……但 Programming.log 的目录结构极其简单:
├── 2024/
│ ├── 03/
│ │ ├── 15-why-i-stopped-using-async-await-for-this-case.md
│ │ ├── 18-debugging-webassembly-module-loading.md
│ │ └── 22-the-real-cost-of-react-context.md
│ └── 04/
│ └── 01-how-i-learned-to-stop-worrying-and-love-the-type-checker.md
├── _index.md # 首页,仅含一句说明和最近 5 篇链接
└── static/ # 存放 favicon.ico 等静态资源
没有
frontend/
或
rust/
文件夹。为什么?因为分类是事后归纳,而思考是即时涌现。当你在调试一个 WebSocket 心跳超时问题时,它可能同时涉及网络协议(OSI 第四层)、浏览器 Event Loop、TypeScript 类型推导、以及公司内部监控系统的埋点逻辑——强行归入某一个分类,等于阉割了问题的立体性。
时间戳才是最诚实的索引。它记录了你认知演化的轨迹:2023 年 7 月你写《为什么放弃 Redux Toolkit》,2024 年 1 月你写《重新理解 RTK Query 的缓存策略》,这两篇之间隔着 6 个月的项目实战、三次线上事故复盘、以及两次团队技术分享。时间序列天然构成一条认知演进线,比任何人工打标都更真实。
实操中,我用 Zola 的
section
功能自动生成年/月归档页,但禁止手动创建分类页。如果某类主题高频出现(比如连续 5 篇都讨论 Rust 的所有权模型),我会在
_index.md
里加一个手动维护的“主题索引”区块,用纯文本链接指向相关日期文件——它不自动更新,但保证每条链接都经过我二次确认,避免机器归类产生的误判。
3. 日志内容的实操方法论:写什么?怎么写?何时写?
3.1 内容边界:只记录三类“不可替代”的信息
Programming.log 不是代码片段库,不是 API 文档备份,更不是每日工作日报。它只收录那些 离开你的大脑就无法存在、且未来大概率需要重新调用的认知资产 。具体分为三类:
第一类:决策背后的“为什么”(Why Logs)
这是日志的核心价值区。例如:
-
为什么选择用
zustand而非jotai管理全局状态?(不是罗列特性对比,而是写:“因项目需支持 SSR,而 jotai 的useStore在服务端渲染时会触发useEffect,导致 hydration mismatch;zustand 的create函数返回 plain object,可安全序列化”) -
为什么将 GraphQL 查询从
useQuery改为useInfiniteQuery?(不是说“为了分页”,而是写:“因后端未提供 total count,客户端需通过 hasNextPage 判断终止,而 useQuery 无法处理动态 pageParam,改用 useInfiniteQuery 后,滚动加载逻辑从 12 行 reduce 变为 3 行 callback”)
这类记录的关键是 暴露权衡过程 。它不追求正确答案,而保存你当时的判断依据——三年后当类似场景重现,你不必重走一遍决策树,只需检索 “zustand SSR” 就能唤起完整上下文。
第二类:失败路径的“断点快照”(Debug Logs)
不是记录“bug 修复了”,而是记录“bug 为什么难发现”。例如:
-
“2024-03-18:WASM 模块加载失败,Chrome 控制台报
TypeError: Failed to execute 'instantiate' on 'WebAssembly'。排查路径:1. 检查.wasm文件 MIME 类型 → nginx 配置缺失application/wasm;2. 添加后仍失败 → 发现fetch()请求头Accept: */*被服务端忽略,强制设置headers: { 'Accept': 'application/wasm' };3. 最终定位:Cloudflare 自动压缩.wasm文件,需在 Page Rule 中禁用 Brotli 压缩。”
这种记录的价值在于 压缩调试熵值 。它把原本需要 3 小时的排查过程,固化为可复用的 checklist。下次遇到同类问题,你直接执行第 1 步检查 MIME 类型,而非从头抓包。
第三类:概念顿悟的“临界点时刻”(Aha Logs)
指那些突然理解某个抽象概念的瞬间。例如:
-
“2024-02-29:终于明白 Monad 不是‘容器’,而是‘计算管道’。
map是对值的转换,flatMap是对计算的拼接。就像 Promise 的.then()不是取值,而是注册下一个异步任务的入口点。之前总纠结 ‘Promise 是 Monad 吗’,现在意识到问题本身错了——应该问 ‘Promise 的链式调用如何体现 flatMap 的语义’。”
这类记录要 拒绝术语堆砌 ,用生活化类比锚定理解。我常要求自己:如果不能用“给实习生讲清楚”的语言描述这个顿悟,就说明还没真正掌握。
3.2 写作技巧:用“工程师的笔”代替“作家的笔”
程序员写日志最大的陷阱,是试图模仿技术博客的写作风格:精心设计开头、铺垫背景、设置悬念、总结升华。Programming.log 需要的恰恰相反——一种 去修辞化、强功能性的书写范式 。
我给自己立了三条铁律:
铁律一:首句即结论
不写“在现代 Web 开发中,状态管理一直是个挑战……”,而写:“放弃 Redux Toolkit 的核心原因是:其
createAsyncThunk
生成的 action creator 无法被 Jest Mock,导致单元测试覆盖率下降 37%。”
理由:日志是给自己看的,大脑在检索时优先匹配关键词。把结论前置,相当于给每篇日志加了隐形 SEO 标题。
铁律二:代码即证据,不解释代码
不写“这里用
useCallback
是为了防止子组件重复渲染”,而写:
// ❌ 错误示范:解释性描述
const handleClick = useCallback(() => {
// 处理点击逻辑
}, [deps]);
// ✅ 正确示范:用 diff 证明必要性
// before: 子组件每次 render 都接收新函数引用,触发无意义 re-render
// after: 仅当 deps 变化时才生成新函数,子组件 shouldComponentUpdate 返回 false
const handleClick = useCallback(() => {
api.submit(formData);
}, [api, formData]);
理由:日志的价值在于可验证。解释可以编造,但代码 diff 是客观事实。未来你看到这段记录,只需把代码粘贴进项目,运行
npm test
即可验证结论是否依然成立。
铁律三:保留原始错误信息,不美化
不写“接口请求失败”,而写:
[ERROR] POST https://api.example.com/v1/users 502 (Bad Gateway)
Response Headers:
date: Wed, 20 Mar 2024 08:22:17 GMT
server: nginx/1.18.0 (Ubuntu)
x-envoy-upstream-service-time: 12000
理由:502 错误本身不重要,但
x-envoy-upstream-service-time: 12000
暴露了上游服务超时(12 秒),这才是根因线索。美化后的描述会丢失关键诊断信号。
3.3 时间管理:嵌入工作流,而非额外任务
很多人放弃日志,是因为把它当成“下班后要额外完成的任务”。Programming.log 的可持续性,来自它与日常开发流程的 零摩擦融合 。
我的标准操作流是:
-
调试时
:当 Chrome DevTools 的 Console 输出第一条错误堆栈,立即暂停,打开
2024-03-15-debugging-webassembly.md,把堆栈粘贴进去,标注当前时间戳; -
Code Review 时
:看到同事提交的 PR 引发思考(如“这个类型守卫为什么没覆盖 null 情况?”),立刻在日志里新建
2024-03-15-code-review-thoughts.md,写下行思考,不求完整,只记火花; - 会议后 :技术方案评审结束,不整理 PPT,而是打开日志,用 5 分钟写下:“达成共识:采用 CQRS 模式,因读写负载差异达 10:1;待确认:事件溯源的 snapshot 策略,建议每 1000 次事件生成一次”。
关键技巧是
永远保持一个日志文件处于“半打开”状态
。我在 VS Code 左侧边栏固定一个
scratch.md
标签页,里面写着:
# Scratch Pad - 2024-03-15
- [ ] WASM MIME type fix: nginx config + Cloudflare rule
- [ ] RTK Query cache key 设计:考虑加入 userRole 字段
- [ ] 会议结论:CQRS 分界点定在 OrderAggregate
这些待办项不是任务清单,而是思考的“暂存区”。当某项被验证或深化,我就把它拖进对应日期的正式日志文件,删除暂存项。这种设计让日志写作变成思考的自然延伸,而非额外负担。
4. 工具链深度配置:从零搭建可复用的日志系统
4.1 Zola 静态站点的精简配置
Zola 的默认配置过于通用,我们需要裁剪出 Programming.log 专用的最小集。以下是
config.toml
的核心配置(已移除所有非必要字段):
# config.toml
base_url = "https://programming.log"
title = "Programming.log"
description = "a place to keep my thoughts on programming"
# 关键:禁用所有非必需功能
compile_sass = false
build_search_index = true # 启用前端搜索
minify_html = true
# 内容组织:只保留时间戳路由
[directories]
content = "content"
output = "public"
# 模板控制:极致简化
[markdown]
highlight_code = true
highlight_theme = "dracula"
# 自定义页面:首页仅显示最近 5 篇
[extra]
recent_posts_count = 5
重点解析
build_search_index = true
:Zola 会自动生成
search-index.json
,配合前端 JavaScript(约 30 行代码)即可实现全文搜索。相比 Algolia,它不依赖外部服务,不产生费用,且搜索结果精准匹配 Markdown 源文件——当你搜索 “React.memo”,结果只会返回包含该字符串的
.md
文件,不会出现 Algolia 常见的“相关但无关”噪声。
实操心得:不要在
config.toml里配置taxonomies(分类)。Zola 的分类功能会为每个标签生成独立页面,增加维护成本。我们的“主题索引”完全由手工维护的_index.md实现,更可控。
4.2 VS Code 插件链:让写作像写代码一样流畅
日志写作的体验,90% 取决于编辑器配置。我构建了一套轻量插件链,目标是: 输入最少字符,获得最多辅助 。
核心插件及配置:
-
Markdown All in One
:启用
enableTitleCase(自动标题大写)、listIndentation(列表缩进智能对齐); -
Paste Image
:截图后 Ctrl+Alt+V 直接插入本地图片,路径自动转为
./static/images/20240315-xxx.png; -
Todo Tree
:识别
<!-- TODO -->注释,右侧边栏实时显示待办项; -
Auto Rename Tag
:修改 HTML 标签时自动同步闭合标签(虽用 Markdown,但偶尔需嵌入
<details>展开块)。
最关键的自定义是
Snippets(代码片段)
。在
snippets/markdown.json
中添加:
{
"Log Header": {
"prefix": "loghead",
"body": [
"---",
"date: ${1:2024-03-15}",
"title: \"${2:Thought Title}\"",
"tags: [\"${3:tag1}\", \"${4:tag2}\"]",
"---",
"",
"${5:# ${2}}",
"",
"> 💡 This is a Programming.log entry — a raw thought, not a polished article.",
""
],
"description": "Insert standard log header"
}
}
输入
loghead
+ Tab,自动展开为带日期、标题、标签的 Front Matter 模板。其中
${1:2024-03-15}
是光标初始位置,按 Tab 键依次跳转,大幅提升结构化写作效率。
4.3 Git 工作流:用版本控制守护思考演进
Programming.log 的 Git 仓库不是用来部署的,而是作为 思考的版本控制系统 。我的提交规范严格遵循 Conventional Commits,但语义被重新定义:
-
feat:表示新增一类思考模式(如feat: add-debug-log-template); -
fix:表示修正过往认知错误(如fix: correct-misunderstanding-of-rust-lifetimes); -
docs:表示更新日志规范(如docs: update-writing-rules-v2); -
chore:表示工具链升级(如chore: upgrade-zola-to-v0.17)。
最关键的是 commit message 的正文必须包含可验证的上下文 。例如:
fix: correct-misunderstanding-of-rust-lifetimes
Before: believed 'static lifetime means global memory'
After: realized 'static means 'valid for entire program duration',
which includes string literals and const values.
Proof: this compiles and runs:
fn get_static_str() -> &'static str { "hello" }
let s = get_static_str(); // s is valid until program exit
这种提交信息,让 Git Log 成为一份可执行的思考演进史。
git log --oneline -n 10
不再是冰冷的哈希,而是认知升级的时间轴。
5. 常见问题与避坑指南:从血泪教训中提炼的 7 条铁律
5.1 问题:日志越写越多,最后变成“数字坟墓”,再也找不到想要的内容
现象 :三年积累 200+ 篇日志,但每次想找“上次解决 WebSocket 心跳超时的方法”,都要翻遍 2023 年下半年的所有文件。
根因 :过度依赖“时间戳”单一索引,缺乏主动维护的语义链接。
解决方案 :建立三层索引体系:
| 层级 | 形式 | 维护方式 | 示例 |
|---|---|---|---|
| L1:时间索引 |
Zola 自动生成的
/2024/03/
归档页
| 完全自动化 |
/2024/03/
页面列出当月所有日志
|
| L2:主题索引 |
手工维护的
_index.md
中的
## Key Topics
区块
| 每月花 10 分钟更新 |
## Key Topics
下列
WebSocket Heartbeat
,链接到
2023-09-12-websocket-heartbeat.md
|
| L3:交叉引用 |
每篇日志末尾的
## See Also
区块
| 写作时即时添加 |
在
2023-09-12-websocket-heartbeat.md
末尾写
## See Also
,链接
2023-08-22-event-loop-timers.md
|
实操心得:L2 主题索引必须手工维护,不能用脚本自动生成。因为只有你才知道“WebSocket 心跳”和“TCP Keepalive”是否属于同一认知范畴。自动化索引会产生语义漂移。
5.2 问题:写着写着变成技术博客,开始在意阅读量和点赞数
现象 :某篇日志发布后收到 20 个点赞,之后几篇明显变得更“精致”:加了封面图、写了引言、结尾加了“欢迎关注”,但写作频率骤降。
根因 :平台机制激活了社会认同需求,覆盖了原始思考动机。
解决方案 :物理隔离 + 心理锚定。
-
物理隔离
:日志源文件(
.md)永远存放在本地~/Documents/programming-log/, 绝不推送到 GitHub 公共仓库 。部署脚本(deploy.sh)只负责将生成的public/目录同步到服务器,源文件不参与传输; -
心理锚定
:在每篇日志开头强制添加注释:
<!-- This is a private thinking log. Not for publication. Not for sharing. Written for my future self, not for readers. -->
每次打开文件,第一眼看到这段话,就是一次认知重置。
5.3 问题:团队协作时,想共享日志,但又怕泄露敏感信息
现象 :想把“微服务间 gRPC 超时配置经验”分享给同事,但日志里混着公司内部域名、监控系统 URL、API 密钥占位符。
根因 :日志内容未做敏感信息分层,公共知识与私有上下文耦合。
解决方案 :实施“洋葱式写作法”——每篇日志分三层:
| 层级 | 内容 | 是否可共享 | 处理方式 |
|---|---|---|---|
| 核心层(Core) | 通用原理、可复用模式、抽象结论 | ✅ 可直接共享 |
用
<!-- CORE -->
标记
|
| 上下文层(Context) | 公司内部技术栈、部署环境、监控工具名 | ⚠️ 脱敏后共享 |
用
<!-- CONTEXT -->
标记,替换为
internal-api.example.com
|
| 敏感层(Secret) | 具体域名、IP、密钥、员工姓名 | ❌ 绝不共享 |
用
<!-- SECRET -->
标记,部署前由脚本自动删除
|
部署脚本
publish.sh
会扫描所有
<!-- SECRET -->
块并移除,确保生成的 HTML 中不包含任何敏感信息。这样,当需要团队共享时,只需将
<!-- CORE -->
和
<!-- CONTEXT -->
部分复制到 Confluence,既保证知识传递,又守住安全底线。
5.4 问题:日志内容越来越“水”,充斥着“今天学了 React”这类无效记录
现象 :翻看 2024 年 1 月的日志,10 篇中有 7 篇是“学习 XXX 的第一天”,内容全是官方文档摘抄。
根因 :混淆了“学习笔记”和“思考日志”。前者记录“我学到了什么”,后者记录“我改变了什么”。
解决方案 :严格执行“30% 规则”——每篇日志中, 描述性内容(What)不得超过 30%,分析性内容(Why/How)不得低于 70% 。
用具体指标衡量:
- 如果一篇日志中,代码块、命令行输出、错误堆栈等“证据型内容”占比 < 20%,视为不合格;
- 如果出现“我觉得”“我认为”等主观表述超过 3 次,必须替换为“实测发现”“调试确认”等客观表述;
-
如果整篇日志没有至少一个
<!-- TODO -->待办项,则说明思考尚未闭环。
我用 VS Code 的 Word Count 插件实时监控比例,写作时右下角始终显示
[Core: 68%] [Context: 22%] [Secret: 10%]
,强迫自己聚焦在 Why 和 How 上。
5.5 问题:移动端无法便捷访问和编辑日志
现象 :通勤路上想到一个好点子,想立刻记下,但手机上只能看 HTML 版,无法编辑源文件。
根因 :日志系统未覆盖“思考发生场景”的全链路。
解决方案 :构建跨设备轻量编辑通道。
- iOS :使用 Working Copy(Git 客户端)+ iA Writer(Markdown 编辑器)。Working Copy 克隆本地仓库,iA Writer 关联该文件夹,编辑后 Working Copy 一键提交;
-
Android
:使用 Termux + git + vim。Termux 安装后执行:
pkg install git vim git clone https://your-server/programming-log.git cd programming-log/content/2024/ vim 03-15-thought.md -
统一入口
:在 Zola 生成的 HTML 首页底部添加一行:
Edit this log: [VS Code](vscode://file/Users/me/Documents/programming-log/content/2024/03-15-thought.md) | [iOS](workingcopy://open?repo=programming-log&path=content%2F2024%2F03-15-thought.md)
这样,无论在办公室、咖啡馆还是地铁上,思考的捕捉延迟都控制在 10 秒内。
5.6 问题:日志内容风格不一致,有的像论文,有的像聊天记录
现象 :2023 年的日志严谨克制,2024 年初突然变得口语化,夹杂大量表情符号和网络用语,导致回溯时理解成本陡增。
根因 :缺乏风格锚点,写作状态随情绪波动。
解决方案
:制定《Programming.log 风格手册》(
STYLE-GUIDE.md
),并内化为编辑器规则。
手册核心条款:
-
禁用词汇表
:
awesome,incredible,literally,basically,just(作为语气词); -
强制结构
:每篇日志必须包含
## The Problem、## My Approach、## What Actually Worked三个二级标题; -
代码规范
:所有代码块必须标注语言(```tsx)且包含最小可运行上下文(如
import { useState } from 'react';); -
长度红线
:单篇日志不超过 1200 字(Zola 模板中用
{{ page.content | truncate(length=1200) }}强制截断)。
VS Code 的 EditorConfig 插件会自动应用这些规则,例如检测到
awesome
一词,下方立即出现波浪线提示:“❌ STYLE: Avoid subjective adjectives”。
5.7 问题:日志系统占用大量磁盘空间,尤其是历史图片和截图
现象
:三年积累,
static/images/
目录达 2.3GB,其中 80% 是重复截图和未压缩 PNG。
根因 :未建立媒体资产生命周期管理。
解决方案 :实施“媒体三原则”:
-
原则一:截图即压缩
macOS 使用内置快捷键Cmd+Shift+5,勾选“选项→存储为→文件”,保存前自动压缩为 WebP(Zola 插件zola-webp自动转换); -
原则二:图片即索引
每张图片命名必须携带语义:20240315-chrome-devtools-network-tab-filter.png,而非Screen Shot 2024-03-15 at 10.22.33.png; -
原则三:定期瘦身
每季度运行清理脚本prune-media.sh:# 删除 180 天前的图片 find ./static/images -name "*.png" -mtime +180 -delete # 删除重复图片(基于 hash) fdupes -rdN ./static/images
实测效果:媒体目录体积从 2.3GB 降至 320MB,且检索效率提升 3 倍——因为图片名自带时间戳和场景,
ls | grep "network-tab"
直接定位目标。
6. 进阶实践:从个人日志到团队知识基座
6.1 团队版 Programming.log 的架构设计
当个人日志沉淀出足够多的“Why Logs”和“Debug Logs”,它自然具备向外辐射的价值。但团队化不是简单地把个人仓库设为公开,而是重构为 可治理的知识基座 。
核心架构采用“中心辐射模型”:
[Team Programming.log]
▲
│ 同步(只读)
┌─────────────┼─────────────┐
│ │ │
[Frontend Log] [Backend Log] [Infra Log]
│ │ │
└──────┬────────┴────────┬──┘
│ │
[Individual Logs] [Individual Logs]
- 中心层(Team Log) :由 Tech Lead 维护,只收录经验证的、跨团队通用的模式(如“微服务熔断阈值设定指南”);
- 领域层(Frontend/Backend/Infra) :由各领域负责人维护,收录领域内最佳实践(如“Next.js App Router 数据获取模式”);
- 个人层(Individual) :完全自主,但鼓励向领域层贡献内容。
关键创新是
“贡献即合并”工作流
:
当某位前端工程师在个人日志中写出《useSWR 与 React Query 的缓存语义差异》,他不直接 PR 到 Team Log,而是:
-
将该日志标记为
<!-- CONTRIBUTION_READY -->; -
运行
contribute.sh脚本,自动提取## The Problem、## What Actually Worked等结构化内容; -
生成标准化 PR 模板,提交至
frontend-log仓库。
领域负责人收到 PR 后,只需做两件事:验证结论是否仍适用(运行测试)、确认是否符合团队技术栈(如是否基于 Next.js 14)。这种设计把知识沉淀的颗粒度控制在“可验证的结论”层面,避免了传统 Wiki 中常见的“观点之争”。
6.2 知识可信度的量化评估体系
团队日志最大的风险是“过时信息污染”。我们引入 Knowledge Health Score(KHS) 机制,为每篇日志赋予动态可信度评分:
| 指标 | 权重 | 计算方式 | 示例 |
|---|---|---|---|
| Age | 30% |
max(0, 100 - (days_since_last_update * 0.5))
| 365 天未更新 → KHS = 100 - 182.5 = 0 |
| Validation | 40% |
每次被其他日志
## See Also
引用 +5 分,被 PR 采纳 +10 分
| 被 3 篇日志引用 + 1 次 PR 采纳 → 25 分 |
| Test Coverage | 30% | 日志中提及的代码方案,若存在对应单元测试,+20 分 |
有
test/useSWR-cache.test.tsx
→ +20 分
|
Zola 的
shortcodes
功能可实现动态评分渲染。在每篇日志顶部添加:
{{ khs_score(page) }}
生成 HTML 时自动计算并显示
KHS: 87/100
。当 KHS < 60 时,页面顶部自动显示警告横幅:
⚠️ This log may be outdated. Last validated: 2023-08-12. Please verify conclusions before applying.
这套机制让知识可信度从主观判断变为客观数据,新人入职时,可直接按 KHS 排序浏览日志,优先学习高分内容。
500

被折叠的 条评论
为什么被折叠?



