Markdown 文档写作完全指南

为什么用 Markdown 写文档

如果你参与过软件开发或者技术团队协作,大概率已经接触过 Markdown 了——GitHub 上的 README、项目 Wiki、技术博客,到处都是它的身影。但很多人只是零散地用着,没有系统地考虑过怎么用它来组织完整的技术文档。

用 Markdown 写文档有几个很实在的好处。它是纯文本格式,任何编辑器都能打开,不依赖特定的软件或平台。这也意味着它天然适合 Git 版本管理——谁改了哪一行,什么时候改的,一目了然。说实话,我之前用过 Word 写内部技术文档,多人协作时合并格式简直是噩梦,后来切到 Markdown 之后,这类问题基本消失了。

另一个好处是可移植性。同一份 Markdown 文件,可以渲染成网页、导出 PDF、转换成 Word,甚至生成电子书。你只需要维护一份源文件,不同输出格式交给工具去处理。

不过 Markdown 也不是万能的。它本质上是一个轻量标记语言,如果你需要复杂的排版(比如多栏布局、精确的页面控制),那 Markdown 并不是最佳选择。对于这类需求,AsciiDoc 或 reStructuredText 可能更合适。但对于绝大多数技术文档场景——API 说明、项目手册、开发指南——Markdown 完全够用,而且上手成本最低。

Markdown 文档的基本结构

一篇结构清晰的技术文档,通常包含这些部分:

---
title: API 接口文档
version: 2.1.0
last_update: 2026-05-14
---

## 概述

简要说明这个接口的用途和适用场景。

## 接口列表

### 获取用户信息

**请求方式**:`GET /api/users/{id}`

**参数说明**:

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | string | 是 | 用户唯一标识 |
| fields | string | 否 | 返回字段筛选 |

**响应示例**:

​```json
{
  "id": "u_10086",
  "name": "张三",
  "email": "zhangsan@example.com"
}
​```

## 错误码

| 错误码 | 说明 |
|--------|------|
| 404 | 用户不存在 |
| 403 | 无访问权限 |

这个模板覆盖了技术文档的核心要素:元数据(frontmatter)、概述、详细说明、示例和错误处理。你可能会注意到,参数和错误码这类结构化数据,用表格呈现比纯文字描述清楚得多。

Front Matter 元数据

文件开头的 --- 包裹部分叫做 frontmatter,用于存储文档的元信息。在静态站点生成器中,这些字段会被读取并用于页面渲染——比如标题、排序、分类、标签等。常见的 frontmatter 格式是 YAML:

---
title: 快速开始
order: 1
category: 入门指南
tags: [安装, 配置, 快速开始]
---

Markdown 标题 和正文之前放置 frontmatter,可以让文档系统自动生成导航、面包屑和搜索索引。这是我搭建文档站点时最基础也最实用的一个习惯。

文档写作规范

标题层级

每篇文档只用一个顶级结构来组织,避免标题层级混乱。具体来说:

  • H2(##)作为主要章节分隔
  • H3(###)用于子章节
  • 尽量不要超过 H4,层级太深说明内容结构需要重新组织
## 安装
### 系统要求
### 下载安装包
## 配置
### 基本配置
### 高级选项

有一个细节值得注意:不要在同一个文件里混用 ATX 风格(#)和 Setext 风格(=== 下划线)的标题。不同 Markdown 解析器对混用场景的处理可能不一致,CommonMark 规范虽然定义了两者的等价性,但部分工具在生成目录时会遗漏 Setext 风格的标题。

代码示例

技术文档里的代码块几乎是标配。几个实用建议:

​```python
def get_user(user_id: str) -> dict:
    """根据 ID 获取用户信息"""
    return db.query("SELECT * FROM users WHERE id = ?", user_id)
​```

首先,始终指定语言标签(pythonbashjson 等),这样渲染时才能启用语法高亮。其次,代码示例要能直接复制运行。我之前写过一篇部署文档,结果里面有个命令少了 sudo,读者直接复制执行后报权限错误,这种细节很容易被忽略但影响很大。

如果命令很长需要换行,用 \ 明确标记续行:

docker run -d \
  --name my-docs \
  -p 8080:80 \
  -v $(pwd)/docs:/usr/share/nginx/html \
  nginx:latest

列表和强调

技术文档中大量使用列表来组织步骤或要点。无序列表用 -*,有序列表用 1.。嵌套列表时保持缩进一致(2 或 4 个空格都可以,但全文统一)。

强调要克制使用。**粗体** 留给真正需要突出的关键词,不要整段加粗——那会让读者分不清重点。*斜体* 适合标注术语或英文缩写的首次出现。

API 文档的 Markdown 写法

API 文档是 Markdown 技术文档中最常见也最有价值的应用场景之一。一套规范的 API 文档通常包含这些部分:

## 创建订单

**接口地址**:`POST /api/v2/orders`

**请求头**:

| 字段 | 值 | 说明 |
|------|-----|------|
| Content-Type | application/json | 请求体格式 |
| Authorization | Bearer {token} | 认证令牌 |

**请求参数**:

| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| product_id | string | 是 | 商品 ID |
| quantity | integer | 是 | 购买数量,最小值 1 |
| coupon_code | string | 否 | 优惠券代码 |

**请求示例**:

​```json
{
  "product_id": "p_20001",
  "quantity": 2,
  "coupon_code": "SAVE20"
}
​```

**响应示例**:

​```json
{
  "order_id": "ord_20260514001",
  "status": "created",
  "total": 199.00,
  "discount": 39.80
}
​```

这种表格+代码块的组合方式,信息密度高、结构清晰,是 API 文档的标准写法。如果接口数量多,建议按模块拆分成多个 Markdown 文件,然后用文档工具自动聚合成完整的 API 参考。

文档工具和生成器

写好 Markdown 文件只是第一步,你还需要工具把它们变成可浏览的文档站点。下面是几个主流的静态文档站点生成器对比:

工具语言特色适合场景
MkDocsPython配置简单、Material 主题漂亮、搜索体验好中小型项目文档、技术博客
DocusaurusReact/Node版本管理、MDX 支持、i18n 国际化开源项目文档、产品文档
HugoGo构建速度极快、适合大型站点大量页面的文档站
DocsifyJavaScript无需构建、运行时渲染、部署简单快速原型、内部文档

MkDocs 实战

我第一次用 MkDocs 搭文档站点,从安装到上线只花了不到半小时。它的核心配置就是一个 mkdocs.yml 文件:

site_name: 我的项目文档
theme:
  name: material
  language: zh
  features:
    - navigation.tabs
    - search.suggest

nav:
  - 首页: index.md
  - 快速开始: getting-started.md
  - API 参考:
    - 用户接口: api/users.md
    - 订单接口: api/orders.md

项目结构也很直观:

docs/
├── index.md
├── getting-started.md
└── api/
    ├── users.md
    └── orders.md
mkdocs.yml

有个坑值得提一下:MkDocs 默认的搜索插件对中文支持不太好,需要安装 mkdocs-material 主题并配置 search.suggest,或者额外集成 jieba 分词。我当时折腾了半天才发现这个问题,后来在 mkdocs.yml 里加了一行 language: zh 就解决了大部分情况。

Docusaurus 适合更大的项目

如果你的文档需要多语言支持或者版本管理,Docusaurus 是更好的选择。它内置了 i18n(国际化)方案,可以为不同语言生成对应的文档目录。而且它支持 MDX——也就是在 Markdown 中嵌入 React 组件,非常适合需要交互式示例的 API 文档。

不过 Docusaurus 的学习成本比 MkDocs 高一些,配置也更复杂。对于个人项目或小型团队,MkDocs 通常足够了。

文档自动化工作流

把文档当代码来管理(Docs-as-Code),是现代技术团队的标准做法。核心思路是:文档和代码放在同一个 Git 仓库里,用同样的分支、PR、Review 流程来管理。

CI/CD 自动部署

以 GitHub Actions 为例,每次推送到 main 分支时自动构建和部署文档:

name: Deploy Docs
on:
  push:
    branches: [main]
    paths: ['docs/**']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install mkdocs-material
      - run: mkdocs gh-deploy --force

这样每次文档更新,站点就会自动重新构建和部署。搭配 paths 过滤器,只有 docs 目录变更时才触发,避免不必要的构建。

Markdown Lint

在 CI 中加入 lint 检查,可以统一团队的文档风格。markdownlint 是最常用的工具:

# 安装
npm install -g markdownlint-cli

# 检查所有文档
markdownlint docs/**/*.md

# 自动修复
markdownlint docs/**/*.md --fix

常见的规则包括:标题层级不能跳级、每行不超过指定长度、代码块必须指定语言、列表缩进一致等。这些规则看起来琐碎,但在多人协作时能有效避免格式混乱。

进阶技巧

Mermaid 流程图

在文档中插入流程图、时序图,可以让复杂的逻辑一目了然。Mermaid 是 Markdown 生态中最流行的图表扩展,大部分文档工具都原生支持:

​```mermaid
sequenceDiagram
    participant 用户
    participant 前端
    participant 后端
    用户->>前端: 提交订单
    前端->>后端: POST /api/orders
    后端-->>前端: 返回订单 ID
    前端-->>用户: 显示创建成功
​```

MkDocs Material、GitHub、Obsidian 都支持直接渲染 Mermaid 图表。需要注意的是,有些静态站点生成器需要额外安装插件才能渲染 Mermaid。

Admonition 提示块

技术文档中经常需要标注提示、警告、注意事项。除了基本的 blockquote(>),很多文档工具支持增强的提示块语法:

!!! note "注意"
    这个接口在 v3 版本中将被废弃,请迁移到 v2/orders。

!!! warning "警告"
    删除操作不可逆,请确认后再执行。

这是 MkDocs Material 主题的语法。Docusaurus 使用的是类似的 :::tip / :::warning 语法。GitHub 则使用 [!NOTE] / [!WARNING] 风格的 Alert 语法。选择哪种取决于你使用的文档工具。

交叉引用和锚点链接

长文档中经常需要跳转到其他章节。Markdown 链接 支持锚点跳转:

详细信息请参阅 [错误码说明](#错误码)。

大部分文档工具会自动根据标题生成锚点(把标题转成小写、空格替换为短横线)。如果你的文档工具支持,也可以用 [链接文字][ref] 的引用式写法,把所有链接定义集中放在文件末尾,保持正文简洁。

常见问题

Markdown 文档和 Word 文档哪个好?

看场景。团队内部的技术文档、API 说明、开发指南,Markdown 更合适——版本管理方便、协作效率高、自动化集成简单。如果是要给外部客户交付的正式文档(合同、报告),Word 或 PDF 更正式。两者不冲突,Markdown 作为源文件,需要时用 Pandoc 转换输出即可。

怎么让团队统一 Markdown 写作风格?

制定一份简单的 Markdown 风格指南,写明标题怎么写、列表怎么缩进、代码块怎么标注语言等基本规则。然后在 CI 中加入 markdownlint 检查,不符合规范的文档会在 PR 阶段被标记出来。比口头约定有效得多。

Markdown 文档怎么生成 PDF?

最常用的方案是 Pandoc。一行命令就行:

pandoc document.md -o document.pdf --pdf-engine=xelatex -V mainfont="Noto Sans CJK SC"

如果文档中有中文内容,必须用 xelatex 引擎并指定中文字体,否则会乱码。MkDocs 也可以通过插件导出 PDF,但配置稍复杂一些。

参考来源