python mkdocs
# Python MkDocs一个文档工具的真实面貌大概是在三年前我接手了一个已经开发了两年的内部框架代码写得相当漂亮但文档散落在十几个Word文档里版本号混乱得让人抓狂。那是我第一次认真琢磨MkDocs后来发现这工具在文档生成这条路上走了一条挺聪明的路。它到底是什么很多人第一次听说MkDocs会以为它是个类似Sphinx的庞然大物。实际上它很简单——一个把Markdown文件转成静态网站的工具。核心逻辑就是把一堆.md文件按照你指定的目录结构生成一套可以直接扔到web服务器上的HTML页面。举个不太恰当的例子就像你把笔记本上写好的笔记按原样打印出来装订成册——MkDocs就是那个打印机和装订机的组合体。它不会帮你重新组织内容不会自动生成流程图也不会从代码里提取文档字符串。它就是个忠实的格式转换器附带一个还算好用的导航系统。设计哲学也很直接你写Markdown它生成网站。没有数据库没有后台没有动态内容。生成的每张页面都是静态HTML这意味着你可以把它托管在GitHub Pages、Netlify或者任何一个支持静态文件的服务器上。这点和Sphinx那种“要把docstring抽出来、把Python模块映射成文档”的思路完全不同。它能干什么最基础的功能是把Markdown转成HTML提供一套默认主题让你点几个按钮就生成一个看起来还不错的文档站点。但我猜你不太在意这个真正让它变得有价值的是另外几件事。主题系统可能是它最讨巧的设计。默认的mkdocs主题很朴素但Material for MkDocs这个第三方主题几乎成了事实标准——搜索、代码高亮、版本切换、多语言支持全都有。有个细节Material主题的搜索是预先生成索引的不像有些方案需要依赖Elasticsearch或者浏览器端解析这就让整个站点的响应速度很快。曾经测试过一个包含500多页的文档集搜索响应时间基本在100毫秒内。插件机制是第二个亮点。你可能需要自动生成API文档有插件。想把注释转换成可视化图表有插件。需要在构建前对文件做些预处理也有插件。不过有一点值得注意——插件质量参差不齐。遇到过几个声称能“一键生成美观文档”的插件实际上只是把代码高亮搞得更花哨了些。还有个容易被忽略的功能它是增量构建的。编辑了一个Markdown文件MkDocs只会重新生成对应的HTML而不是整个站点。这在文档比较大的时候能节省不少时间。曾经维护过一个2000多页的文档库全量构建需要大约45秒但增量构建只需要2-3秒。怎么使用安装特别简单一行命令就行pipinstallmkdocs然后是初始化mkdocs new my-projectcdmy-project这会生成一个docs目录和一个mkdocs.yml配置文件。默认的docs目录下已经有个index.md你可以把它理解成首页。编辑mkdocs.yml告诉它你的文档结构site_name:我的文档nav:-首页:index.md-入门指南:getting-started.md-API参考:-核心模块:api/core.md-工具函数:api/utils.md然后用mkdocs serve启动本地开发服务器浏览器打开http://127.0.0.1:8000就能看到效果。每次保存文件页面会自动刷新。当你觉得差不多了运行mkdocs build所有静态文件会生成在site目录下。把这个目录丢到服务器上就行。有个小技巧如果你想让站点看起来更专业可以搭配Material主题pipinstallmkdocs-material然后在mkdocs.yml里修改主题theme:name:material主题配置起来有点东西。比如如果你想自定义颜色直接抄Material的色板就行theme:palette:primary:indigoaccent:deep orange最佳实践这几年踩过不少坑说几个实实在在的建议。关于目录结构不要学Sphinx那种“把文档和代码放在同一个仓库”的做法。MkDocs最好独立成一个单独的文档仓库尤其是当你的项目已经有复杂的CI/CD流水线时。曾经因为把文档和代码混在一个仓库里每次代码更新都要重新构建文档结果就是文档构建时间从不到1分钟变成了17分钟。分开之后文档仓库的CI只负责文档清爽得很。关于导航导航结构最好保持扁平嵌套不要超过三层。超过三层用户找东西就变得像在翻一个没目录的文件夹。另一个问题如果导航项超过15个用户通常会失去耐心。一个解决办法是把不常用的内容放到“附录”或者“参考”部分用标签页或者下拉菜单收纳起来。关于版本管理MKDocs本身不提供版本控制但Material主题有个版本切换功能。做法是在site目录下放一个versions.json文件指定不同版本的路径。生产环境里可以把这个和CI结合——每次发布新版本的时候自动把旧版本的文档归档然后添加新版本。这样用户就能随时切回旧版本文档而不必去Git仓库翻历史。关于图片和资源这是一个常见的陷阱。很多开发者直接把图片放到docs目录下但MkDocs在处理图片路径时有点特别。一是图片路径要相对于docs目录而不是相对于当前Markdown文件的路径。二是个坑如果你在多个页面引用同一张图片最好把图片放在一个独立的assets或img目录里不然更新图片时所有引用它的文件都要改路径。关于自定义CSS/JS可以通过extra_css和extra_javascript引入外部文件。一个常见的需求是添加自定义的代码块样式比如给不同语言的代码块加上不同的边框颜色。做法是在docs目录下创建css/custom.css然后在mkdocs.yml里配置extra_css:-css/custom.css同类技术对比这个领域其实竞争者不多但各有各的调性。Sphinx如果要说MkDocs有什么天然的对手那就是Sphinx。Sphinx更适合那种需要从Python源码自动生成API文档的场景——它会解析你的rst文件也会从模块的docstring里抽内容。MkDocs没有这个能力你需要在Markdown里手动写API文档。但Sphinx的缺点是太重了安装Sphinx及其依赖文件体积大概在50MB左右而MkDocs加上Material主题也才20MB出头。Sphinx的学习曲线也陡峭——reStructuredText语法本身就有不少特殊规则配置起来也颇为复杂。GitBook一度很流行但现在基本被放弃了维护。GitBook的编辑器挺好用但生成的文件结构复杂严重依赖他们的云服务。如果哪天GitBook公司倒闭你自己生成的文件可能就打不开了——这不是危言耸听早年用GitBook的几个开源项目已经遇到了这个问题。MkDocs生成的是纯静态HTML不存在这个风险。DocsifyDocsify是个比较文艺的选择——它不需要构建步骤直接读取Markdown文件在浏览器端渲染。这意味着你只需要一个简单的HTTP服务器就能运行文档。但它的缺点很明显首屏加载慢SEO不友好搜索引擎爬虫抓不到内容而且需要用户端有JavaScript支持。MkDocs是静态生成HTML即使关闭JavaScript也能正常浏览。Docusaurus这是Facebook出的工具功能和MkDocs类似但用React构建。Docusaurus支持版本管理、i18n、搜索功能很全。但如果你团队里没有React经验学习和维护成本会比MkDocs高。MkDocs用Python和Markdown这对Python开发者来说几乎是零学习成本。有个有意思的观察如果你的文档页数少于50页或者团队里主要是Python开发者用MkDocs会比较顺手。如果你的文档超过200页或者需要从源码自动生成大量API文档Sphinx可能是更好的选择。而如果你的文档主要受众是前端开发者Docusaurus的体验会更好。回到开头说的那个内部框架最后用MkDocs重建了文档配合Material主题和几个插件效果还不错。当然也有遗憾——有些从Sphinx迁移过来的项目初期总有人抱怨找不到API文档因为MkDocs不支持自动抽取docstring。后来想了个折中方案用mkdocstrings插件配合sphinx-style的注释格式勉强实现了类似的效果但总归不如Sphinx来得纯粹。这大概就是MkDocs的定位——它不强求做所有事情但把文档生成这件事做到足够好用。你不需要是个全栈工程师不需要懂React或者RST语法只需要会写Markdown就能生成一套能见人的文档。对于大多数Python项目来说这已经足够了。