从Markdown到静态站点:我的极简个人文档发布方案
老实说我一开始也没想到会为“rea”这个看起来没啥信息的名字折腾这么久。事情起因很简单我长期维护一个个人技术笔记库里面攒了几百篇Markdown文档包含大量临时记录、代码片段、项目复盘和日常踩坑备忘初期一直依赖现成的静态站点生成方案但用着用着总觉得极度别扭——配置越堆越厚构建越来越慢明明只想写点东西最后反而被工具链拖住了。后来我花了不少时间把整套发布流程压缩到几条命令核心思路就是围绕一个我私下叫“rea”的精简渲染方案做文章。这篇文章就把从需求判断、目录设计、构建链路到部署维护的完整过程摊开讲适合那些跟我一样手里有大批Markdown笔记、又不想被重型框架绑架的开发者参考。它不是一篇工具评测也不是文档翻译而是一个真实项目在反复取舍后留下的实操切片。1. “它不是框架”我是如何确定rea的定位的1.1 需求是从上百篇零散文档里逼出来的每个人的笔记库都会有一个失控期。我早期有相当长一段时间是随手乱放文档今天新建一个Note_20250115.md明天又建一个最终版V3.md偶尔还会把图片、PDF一并塞进同一个文件夹。等到某天真正想找一篇关于某次调试过程的记录时才发现内容堆积得毫无规则搜索还得靠文件管理器逐个点开。这时候我意识到我需要的不是一个“花哨的博客系统”而是一个能让我快速把Markdown文档变成可浏览网页结构的最小化发布方案。我希望它做到三件事输入只要求Markdown纯文本输出只要求静态HTML文件中间过程不引入数据库、不依赖在线服务。rea这个代号也是这时候定的——“简单、直接、不需要多余东西”它后来成了一种设计准则而不是某个具体产品的名字。很多人会问既然已经有那么多成熟工具为什么还要自己动手我的理由很现实绝大多数现成方案都默认你要配置主题、分类、标签体系、社交链接、评论系统等一堆东西而我的核心需求只是“把Markdown变成一组可以通过浏览器阅读的HTML页面”。工具链越复杂日常维护成本越高一旦某个依赖升级导致构建失败我还得花时间排查。这对我来说是完全不必要的负担。某次我遇到过一次上游依赖接口变更整整一个晚上都在修构建问题而不是写文档。也就是那一次之后我开始思考一个极简的自建方案把控制权完全拿回自己手里。我给自己定的硬约束是所有核心依赖尽量只保留Markdown解析和HTML生成两个环节其余功能能砍则砍保证即使三年后回来依然能在一分钟内跑通发布流程。1.2 rea与传统建站方案的关键取舍如果纯粹为了写作直接用Git托管Markdown也能活但可读性和检索性会很差。如果用重型静态站点生成器功能固然丰富但学习成本和配置成本双双上升。我最终选择的方案用一个公式可以说明白rea Markdown解析器 模板渲染 本地目录结构不依赖数据库与常见方案相比这套路线的核心差异有几处内容组织形式完全不同传统方案通常要求你把日期、分类、slug等信息塞进文件头部FrontMatter而rea直接使用文件目录和文件名的结构来推导这些信息等于用文件系统本身承担了元数据管理职责。没有“标签系统”的概念而是通过自动扫描每个文档中出现的关键词来生成关联索引。这个设计会在后面详细讲好处是写文档时完全不用维护元数据标签坏处是算法的准确性需要调优。发布形态是纯静态的HTML文件组任意HTTP服务器、任意托管环境都能跑不需要服务端解析不需要PHP/Python运行时。这也意味着迁移成本极低——换一台机器只需把整个文件夹拷贝过去部署即完成。我在取舍时还有一个很重要的判断这个方案只面对“我自己的个人文档库”不需要考虑多人协作。因此很多为了协作而设计的机制权限、审核、多用户都不是必需品。这也让rea可以走一条极致精简的技术路线。后续所有步骤、配置、命令都是在“个人单用户、离线优先、长期可维护”这三个前提条件下展开的。如果你需要的是一个团队知识库或多作者平台那rea的设计思路可能并不适合你这一点我希望读者能提前判断清楚。2. 目录设计用文件系统做元数据库2.1 源文件目录划分的“最小但可扩展”原则我用了相当长时间琢磨目录结构最终确定的方案其实非常朴素把整个内容库分成content/、assets/、output/和theme/四个目录。content/存放全部Markdown源文件它内部再按主题分子目录比如backend/、frontend/、devops/、notes/等这个分类完全跟随我自己的工作领域不做抽象总结保持直观。assets/统一存放图片、附件、参考文件便于构建时批量复制。output/是构建产物目录每次发布都会整体重刷保证每个HTML文件都是最新版本。theme/则存放模板、样式和脚本资源。之所以坚持“目录即元数据”是因为我发现给每篇文档维护FrontMatter里的title、date、categories字段本质上是把信息写两遍一遍在文件本身一遍在文件头部这是维护成本的重复。文件系统已经能告诉我文件名、创建时间、所在目录、相对路径如果我在构建阶段读取这些信息并自动换算成页面的标题、分类和URL路径就不需要额外去维护一套元数据。唯一需要额外记录的是“展示用标题”和“发布日期”因为我经常给文件起英文名而展示时想要中文标题。所以rea规定每个Markdown文件头部可以有一段极简的YAML块可选字段只有title和date其余信息一律靠路径推导。这个设计在用了几个月后确实极大降低了新增页面的摩擦成本——我只需要把.md文件丢进对应目录构建脚本就会自动认出它。2.2 文件命名规范与排序策略rea的命名规则简单到近乎苛刻要求Markdown文件名必须使用数字序号_英文slug.md的格式例如01_rea-introduction.md、02_file-system-as-database.md。前缀数字的作用有两个一是直接决定文章在目录列表中的排序二是用来避免文件名出现中文导致URL编码混乱。slug部分用短横线连接的小写英文词组表达内容主题。这种规则牺牲了一点写文件的随意性换来了构建脚本极大简化——我不用在每次生成页面时再去分析乱七八糟的文件名逻辑判断变得非常稳定。排序策略是按“数字前缀升序”即我默认数字小的内容先创建、位置靠前但这个规则并不是死板的。有些文章我会特意用00_开头作为某个子目录里的置顶条目有些系列文章会连续编号这样浏览时从列表顶部就能看出开发脉络。更细节的做法是构建脚本里定义了一个NAV配置允许在每个子目录下放一个_index.md作为目录首页说明。这个文件不会生成独立页面而是作为该目录列表页的导语呈现在顶部相当于提供了一个手工控制的“栏目简介”区域。对于想更自由调整导航顺序的人来说唯一要掌握的就是“数字前缀”这一套约定其余全都由脚本自动处理。3. 核心构建链路从Markdown到静态页面的关键实现3.1 Markdown转换管线是怎么设计的构建的核心算是一条流水线读取Markdown文件→解析内容→填充模板→写入HTML文件。我选用了一款成熟的开源Markdown解析库来承担格式转换同时自己只写了大约300行代码来把解析结果和模板引擎衔接起来。为什么不全自己写解析器我的理由是Markdown语法边界太多普通段落、代码块、嵌套列表、表格、引用甚至嵌入HTML都是不能出错的功能点自研解析器的成本远高于收益。反而是模板引擎这部分因为输出格式完全由我自己掌控并不需要复杂的逻辑所以自己定义一个极简的占位符替换机制就够了。模板渲染我采用的思路是“两级拼接”第一级把Markdown解析出的HTML整段包进article骨架第二级把article内容再嵌入整个页面的布局层。相当于每个页面有两个模板文件post.html负责文档内部结构layout.html负责外围的导航、页脚和样式引用。这样做的好处是改样式不需要碰文档内容结构改单篇文章的观感也不会影响到全局布局。构建时还会对每篇文章做“上一篇/下一篇”的导航计算计算逻辑很简单按照目录遍历顺序找到当前文档的前后邻居把标题链接渲染在页面底部。这些细节虽然不复杂但能明显提升连续阅读的体验——浏览笔记时不必每次返回到列表页重新找下一篇。3.2 目录索引与关键词关联的实现思路生成目录索引页是rea和单纯“逐页转换”的重要区别。构建脚本每处理完一个子目录就会为该目录生成一个index.html里面列出该分类下的全部分文章按数字前缀排序标题下方附一行摘要。摘要怎么来我规定Markdown文件开头除了可选的YAML块之外第一个自然段就是摘要把它截断到120个字符展示。这样做省去了“手动维护摘要字段”的麻烦。因为摘要本身就存在正文开头里写内容时没人会刻意空着开头所以几乎所有页面都有自动摘要可用。跨目录的关键词关联是另一个有意思的实现。我不是通过FrontMatter维护标签而是构建时给每个内容目录维护一个词频表统计所有文档中出现频次较高但不在停用词列表里的词汇构建完成后生成一个统一的keywords.json。用户在页面侧栏点击“相关关键词”就能看到包含该词的其他文章链接。这里踩过的最深的一个坑是中文分词问题——直接按空白字符分割对中文句子完全无效。我的临时解决方式是接一个轻量的分词模块配合自定义词典迭代补充。尽管这个方案不算特别智能但对我个人文档库规模来说已经够用而且完全不依赖在线服务离线状态下照样能构建。3.3 主题与样式接入的具体做法rea的视觉呈现走的是“极简文档风格”路线。我把样式集中在theme/static/css里包括几部分基础排版样式、代码高亮样式、响应式布局定义。代码高亮我选择在构建阶段直接生成带CSS类名的HTML而不是运行时用JavaScript高亮这样页面在关闭JS后依然能看到彩色代码也减少了一个外部脚本依赖。实现方式很直接Markdown解析库把代码块提取出来后交给一个带语言识别能力的语法高亮器处理。这一步比较耗时所以我会做一层缓存如果源代码文件的哈希值没有变化就直接沿用上次生成的高亮HTML片段构建速度能提升很多。导航栏则完全由目录结构派生——读取content/下的一级子目录列表生成顶部导航链接。样式细节上我刻意不给每个分类分配不同的强调色而是整站采用同一种主色调少量中性色因为这样做能在长期更新中避免“配色选择困难”也更容易让读者把注意力放在文字本身。“内容比装饰重要”这句话在rea上不是口号而是通过技术选型直接落实的。4. 三个本地命令搞定全套流程4.1 从编辑到预览rea的日常闭环整个rea使用流程可以用三条命令概括rea init my-notes cd my-notes rea new backend/网络重试机制踩坑 rea serve第一行命令会按照上面说的目录规范创建一个空白内容库第二行在对应子目录级联生成文件名带日期前缀的Markdown模板第三行会执行本地预览——启动一个监听文件变化的小型HTTP服务并把浏览器自动指向本地地址。日常写作时我基本只用到rea new和rea serve写完保存浏览器自动刷新所见即所得。这里有个很细节的设计rea serve的监听只针对content/和theme/目录构建缓存存在output/.cache里这样当我编辑一个文档时脚本只重新渲染相关页面而不是全量刷新。实测下来即使内容库有几百个文档单次增量构建也能保持在几十毫秒级别编辑体验接近实时。4.2 离线发布与增量构建机制发布时执行rea build它会做三件事清空output/下的旧HTML、全量重新生成目录索引和关键词索引、把assets/目录同步过去。听起来是“全量构建”但因为有缓存层实际需要完整渲染的只有变化过的页面静态素材则通过哈希对比跳过重复复制。这里我觉得有一个值得分享的判断为什么发布时用全量模型而不是纯增量模型因为output目录本身是可丢弃的产物保证“任何一次build都能从零恢复整个站点”比“构建速度最快”更重要。一旦output里混入上次没清掉的废弃文件长此以往就会出现“本地显示正常、线上一直有脏页面”的诡异问题这种问题排查起来比重新全量构建一次要费事得多。发布到公网我采取的是一个极简的方案直接用同步工具把output/推送到任意对象存储或普通Web服务器目录。没有引入预处理流程没有后端渲染也不需要CDN回源配置。每次推送完我习惯性地用浏览器无痕窗口检查一遍几个关键页面确认HTML中的相对链接都正确。在rea的目录结构里页面之间大量使用相对路径跳转../notes/xxx.html这样即使整个站点部署在一个子目录下也不会出现链接失效。很多时候人们喜欢用绝对路径图省事但部署环境一换绝对路径就成了最坑的东西。rea从一开始就强制相对路径策略算是从根上杜绝了这类部署问题。5. 使用rea过程中反复踩到的坑5.1 中文文件名、URL编码和服务器兼容性最早我把文件名中文化过一阵子比如使用手册.md本地构建一切正常但部署到某台服务器后发现部分Web服务器对非ASCII字符的文件URL处理方式不统一有的会自动编码有的直接返回404。后来我彻底放弃中文文件名全面改用“数字前缀英文slug”标题的中文展示靠文件头部的title字段解决。这个问题看似细小却花了我最多时间——因为本地一切正常线上偏有问题最后还是用排除法逐个请求URL才定位到编码环节。所以现在我的建议非常明确源文件名尽可能只用[a-z0-9_-]展示信息放头部元数据别指望文件系统替你处理国际化文件名。5.2 相对路径与资源引用的三角冲突静态站点里最常见的两个资源引用场景是页面内引用图片以及引用其他页面。rea的目录结构有层级如果直接在Markdown里写![图](./assets/x.png)最终页面生成的HTML相对路径会跟Markdown源文件所在的相对位置有关必须要经过一次路径换算。我一开始用简单字符串替换处理很快发现子目录深一两层之后路径就变得乱七八糟。后来我改用“以assets/为根目录”的统一约定在Markdown里引用图片时一律写/assets/xxx.png这种根相对路径然后在构建阶段根据目标页面的输出深度自动转换../层级。这一步虽然让脚本逻辑变复杂但换来的是所有文档里引用图片的写法和页面输出的深度无关。如果你要模仿这个方案我强烈建议在一开始就引入这个转换逻辑否则后期页面层级一变深你会被一堆修不完的相对路径折磨。5.3 增量构建里隐藏的“幽灵页面”综合前面提到的“全量发布增量渲染”我遇到过一次最典型的问题某篇文章被移除了但它的HTML页面还残留在output目录中导致搜索引擎和本地浏览都能看到一篇已经不存在的文档。我初期没有太在意清理问题直到一次域名迁移时用爬虫抓链接才发现几十个陈旧页面占了不少空间也干扰了站点结构。之后我在rea build里加入了一项清理机制全量计算当前内容库应当生成的页面清单然后删掉output中所有不在清单内的HTML文件再把新生成的页面写入。说白了就是每个构建任务结束前做一次“期望状态与真实状态的收敛”这才彻底解决了幽灵页面问题。这条经验对任何静态站点的发布流程都有参考价值不要只关心构建生成了什么更要关心这次构建之后该删除什么。6. 进一步改造rea的可能方向经过这轮实践我自己对rea的核心成果进行了总结其实最重要的不是代码实现而是那套“用最少规则约束内容组织方式”的思维方式。它让我意识到一个工具如果让你在写作时还要想着维护元数据你就已经在承担隐形税了。rea主动把元数据负担丢给文件系统和目录规则每次新增文章的成本趋近于零。这套逻辑思路完全可以移植到别的项目里无论你是做一个个人看板、一个内部工具文档站还是整理电子书素材库“让文件系统替你记住结构”都是一个极其有效的基本原则。目前我还在尝试给rea补上两个能力一是支持短代码方便在不写HTML的前提下嵌入视频、代码块折叠等富交互元素二是做一个简单的阅读进度统计通过本地存储记录哪些文档读过、哪些还没读。考虑到单人使用的规模这些功能都不需要做成通用能力只要能解决我自己的需求并保持不超过一千行代码的实现体重就算是在rea的设计约束之内成功了。现在我每次打开笔记库写新文档时几乎已经感觉不到“工具”的存在这就是我觉得这个项目值得写下来的原因。

相关新闻

体素编辑器 ArtCraft:从数据结构到渲染管线的完整实践探索

体素编辑器 ArtCraft:从数据结构到渲染管线的完整实践探索

刚开始看到"ArtCraft"这个名字的时候,大多数人会以为它又是一个给游戏美术团队用的素材平台。但如果你在独立开发或者小团队里待过,就会明白市面上缺的往往不是一个"能画画的软件",而是一个"能让你把脑子里的立体造…

2026/10/18 15:29:03 阅读更多 →
JavaWeb开发者学Vue:前后端分离下的数据驱动与接口联动

JavaWeb开发者学Vue:前后端分离下的数据驱动与接口联动

1. 为什么第二天的主题是Vue如果你正在走JavaWeb的学习路线,第一周基本都是在跟Servlet、Request、Response、JSP打交道,脑子里的画面还是后端Java代码一层一层往外吐HTML。到了Day02突然切入Vue,很多人第一反应是:我一个学后端的…

2026/10/18 15:29:03 阅读更多 →
macOS SVN客户端选择指南:命令行与主流GUI对比

macOS SVN客户端选择指南:命令行与主流GUI对比

1. 从命令行到图形界面:macOS 上 SVN 客户端的真实处境先说一下现状。很多开发者在 macOS 上用 SVN,常被问一句“都什么年代了还用 SVN”?客户端选择也确实比 Git 少一大截——Git 有五花八门的 GUI,配置顺手又快,SVN …

2026/10/18 15:29:03 阅读更多 →

最新新闻

鸿蒙开发入门:用React Native实现日期天数计算工具

鸿蒙开发入门:用React Native实现日期天数计算工具

最近有个朋友问我,小白想接触鸿蒙开发,又不想一上来就被原生工程的各种配置劝退,有没有门槛低一点、又能看到实际效果的项目。我每次都建议先从 React Native 跨平台切入,第一个练手项目就做“日期天数计算工具”。原因很简单&…

2026/10/18 16:31:36 阅读更多 →
EmulatorJS 版本选择指南:跑通浏览器模拟器后,到底该挑哪个分支

EmulatorJS 版本选择指南:跑通浏览器模拟器后,到底该挑哪个分支

EmulatorJS 版本选择指南:跑通浏览器模拟器后,到底该挑哪个分支 【免费下载链接】EmulatorJS A web-based frontend for RetroArch 项目地址: https://gitcode.com/GitHub_Trending/em/EmulatorJS 刚把 EmulatorJS 部署起来,准备挑个版…

2026/10/18 16:31:36 阅读更多 →
Unity Package 源码调试:将包本地化,让断点在 Visual Studio 中真正命中

Unity Package 源码调试:将包本地化,让断点在 Visual Studio 中真正命中

在 Visual Studio 里调试 Unity Packages 里的插件源码,这事看着不难,实际操作却容易让人卡一下午。你在某个包的方法上按下 F9,断点圆圈却是空心的,提示“当前不会命中断点”,再一查模块列表,连符号都没加…

2026/10/18 16:31:36 阅读更多 →
Vue3中用Canvas渲染富文本:告别contenteditable的完整实战指南

Vue3中用Canvas渲染富文本:告别contenteditable的完整实战指南

简介:Canvas-editor是一款基于TypeScript编写的高灵活性编辑器,其Vue3可运行源码包面向需要将此类编辑器集成到业务系统中的前端开发者,尤其适合官方文档不够直观时,希望通过源码学习和二次定制的场景。压缩包为zip格式&#xff0…

2026/10/18 16:31:36 阅读更多 →
Wi-Fi驱动异常排查:PCIe BAR读全FF背后的MSI中断重映射问题

Wi-Fi驱动异常排查:PCIe BAR读全FF背后的MSI中断重映射问题

如果你在调 Wi-Fi 驱动时遇到过read return 0xffffffff、BAR 空间里读出全 FF、或者/proc/interrupts里对应设备那列中断计数纹丝不动,那你大概已经体会过这种感觉:驱动还挂在设备上、配置空间也还活着,但设备和主机之间其实已经断了。这篇笔…

2026/10/18 16:31:36 阅读更多 →
火星探测车路径规划:Fast Marching方法实战与避坑指南

火星探测车路径规划:Fast Marching方法实战与避坑指南

简介:火星探测车在未知复杂地形中的自主导航,是深空探测任务的关键技术之一。这份PDF资料聚焦基于快速行进法(FMM)的路径规划研究,系统介绍改进算法:利用加权速度矩阵W综合评估地形坡度、粗糙度、障碍物和沙…

2026/10/18 16:30:36 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →