Quartz component

针对“搭建个人知识博客,支持检索与思维导图”的需求,结合 2025 年的技术趋势和你的开发者背景,我为你推荐以下三套目前最主流且好用的解决方案。

相比之前的推荐,这次我重点加入了Quartz v4,这是目前知识管理圈(Digital Garden)最火的现代化方案。

方案对比速览

dfg方案核心定位检索能力思维导图/图谱适合人群推荐指数
Quartz v4双链数字花园 (Obsidian 最佳伴侣)内置全文搜索 (无需配置) (Mermaid + 全局关系图谱)笔记重度用户、Obsidian 用户⭐⭐⭐⭐⭐
VitePress高性能文档站 (VuePress 的继任者)内置 Local Search (极速)中 (需插件支持 Mermaid)前端开发者、追求极致性能者⭐⭐⭐⭐
Docusaurus企业级知识库 (功能最全)插件支持 (Algolia/Local)强 (原生支持 Mermaid)需要复杂分类、React 开发者⭐⭐⭐⭐

方案一:Quartz v4 (最推荐 - 打造“第二大脑”)

如果你习惯用 Obsidian 记笔记,Quartz v4 是目前的终极方案。它不是简单的博客,而是数字花园 (Digital Garden)。它能完美还原 Obsidian 的双向链接、关系图谱,而且完全免费

  • 核心优势

    • 无缝对接 Obsidian:支持 Wiki Links [[链接]]、Callouts、LaTeX 公式。
    • 知识可视化:自带全局关系图谱 (Graph View)局部关系图,这是传统博客没有的。
    • 悬浮预览 (Hover Preview):鼠标停在链接上会像维基百科一样显示预览卡片。
    • 极速检索:内置了非常快速的全文搜索,支持快捷键 Ctrl+K 呼出。
  • 思维导图支持: 原生支持 Mermaid。你在 Markdown 里写 mermaid 代码块,它自动渲染为图。

    graph TD;
    A[核心概念] --> B(关联知识);
    A --> C(延伸阅读);
    
  • 搭建方式

    1. 克隆仓库:git clone https://github.com/jackyzha0/quartz.git
    2. 安装依赖:npm install
    3. 放入笔记:把你的 Markdown 文件扔进 content 文件夹。
    4. 启动:npx quartz build --serve

方案二:VitePress (最快 - 极简主义者的首选)

如果你觉得 Docusaurus 配置略显复杂,或者 VuePress 构建太慢,VitePress 是 2025 年的最佳替代品。它是 Vue 官方团队推出的,基于 Vite,构建速度极快,默认主题非常简洁现代。

  • 核心优势

    • :冷启动和热更新几乎是瞬时的。
    • 内置搜索:默认集成了 MiniSearch,配置一行代码即可开启本地全文检索(支持中文)。
    • Markdown 扩展:支持在 Markdown 中直接运行 Vue 组件。
  • 思维导图支持: VitePress 默认不带 Mermaid,需要安装插件 vitepress-plugin-mermaid。 配置后同样支持标准 Mermaid 语法。

  • 搭建方式

    # 初始化
    npm add -D vitepress
    npx vitepress init
    

    config.js 中开启搜索:

    export default {
      themeConfig: {
        search: {
          provider: 'local' // 开启本地全文搜索
        }
      }
    }
    

方案三:Docusaurus (最稳 - 结构化知识库)

如果你需要的是一个文档层级非常深、分类非常严格的“知识库”(类似产品说明书),Docusaurus 依然是王者。它的侧边栏目录管理是所有方案里最强的。

  • 核心优势
    • 文档版本控制:支持给知识库打版本(如 v1.0, v2.0)。
    • React 生态:如果你懂 React,可以随意魔改组件。
    • 博客与文档并存:可以同时拥有“日记流”的博客和“结构化”的文档库。
  • 思维导图支持: 原生支持 Mermaid,只需在 docusaurus.config.js 中开启即可(参考上次历史对话中的配置)。

总结建议

  1. 如果你想展示“思考的过程”和“知识的连接”:选 Quartz v4。这种“数字花园”的形式非常适合个人知识沉淀,酷炫且实用。
  2. 如果你是前端开发者,想要一个极速、干净的博客:选 VitePress
  3. 如果你需要管理海量、多层级的结构化文档:选 Docusaurus

建议先尝试 Quartz,它的“Obsidian 兼容性”和“关系图谱”功能对于知识管理来说是降维打击。

安装报错解决方案 Failed to emit from plugin CustomOgImages: fetch failed

npx quartz build --serve
 
 Quartz v4.5.2  
 
Cleaned output directory `public` in 2ms
Found 0 input files from `content` in 12ms
Parsed 0 Markdown files in 1ms
Filtered out 0 files in 5μs
 
Warning: you seem to be missing an `index.md` home page file at the root of your `content` folder (`content/index.md does not exist`). This may cause errors when deploying.
 Emitting files: ComponentResources -> public/postscript.js
 
 ERROR 
 
 Failed to emit from plugin `CustomOgImages`: fetch failed
     at node:internal/deps/undici/undici:14900:13
     at processTicksAndRejections (node:internal/process/task_queues:105:5)
     at fetchTtf (../util/og.tsx:92:23)
     at ../util/og.tsx:33:18
     at async Promise.all (index 0)
     at async Promise.all (index 0)
     at getSatoriFonts (../util/og.tsx:54:36)
     at Object.emit (../plugins/emitters/ogImage.tsx:116:21)
     at ../processors/emit.ts:24:28
     at async Promise.all (index 10)

这是因为 Quartz v4 默认开启了“社交预览图生成” (OG Image) 功能,而这个功能需要联网去 Google Fonts 下载字体(通常是 Inter 字体),因为网络原因(fetch failed)导致下载失败,从而报错退出。

对于个人知识库来说,这个功能不是必须的(它只是为了让你把链接发到推特/Facebook 时显示一张好看的卡片)。

🚀 快速修复方案

你可以直接在配置文件中禁用这个插件,这样构建速度会更快,且不需要联网下载字体。

第一步:修改 quartz.config.ts

  1. 用编辑器打开项目根目录下的 quartz.config.ts 文件。

  2. 找到 plugins: { emitters: [ ... ] } 这一块配置。

  3. 找到其中包含 ContentMeta 或者 Component.ContentMeta() 甚至直接叫 Plugin.ContentMeta() 的部分?

    • 纠正:在最新的 v4 版本中,生成图片的插件通常叫做 Plugin.ContentPage() 里的配置,或者是单独的 Plugin.OgImage() / Component.CustomOgImages()
    • 根据报错 Failed to emit from plugin CustomOgImages,请在 emitters 列表中找到类似 Plugin.ContentMeta(旧版包含)或 Plugin.ComponentResources 附近。
    • 最直接的方法:在文件中搜索 OgImagesocial 相关的关键词。如果不确定,直接注释掉 这一行(或者把它的配置关掉)。

    通常默认配置长这样(如果有 Plugin.ContentMeta(),它通常负责生成元数据,而图片生成可能在 Transformer 或 Emitter 中):

    但是,最稳妥的解决 fetchTtf 报错的方法是配置 字体不从网络下载禁用图片生成

    更简单的修改方法 (推荐): 找到 quartz.config.ts 中的 config.configuration.cdnCaching,将其改为 false 试试(但这可能导致它尝试本地查找字体,如果本地没有还是会报错)。

    最佳方案:禁用 OG Image 插件quartz.config.tsemitters 数组中,找到类似下面这一行并注释掉

    // Plugin.ContentMeta(), // <-- 如果是这个导致,或者
    // Plugin.NotFoundPage(), 
    

    注意:具体的插件名可能是 Plugin.ContentMeta 或者在较新版本中集成了。如果找不到明确的 OgImage,请尝试在 quartz.config.ts 搜索 fetchTtf 是找不到的,这是源码里的。

    准确操作: 由于 Quartz 更新很快,如果找不到 OgImage,请直接搜索 typography 配置,将 cdnCaching: true 改为 cdnCaching: false 看看能否绕过(通常不能)。

    终极大法: 打开 node_modules/@jackyzha0/quartz/quartz/plugins/emitters/ogImage.tsx (如果能找到) … 不推荐。

    建议: 你的 quartz.config.ts 里应该有一行 Plugin.ContentMeta() 或者类似的。在 v4.5.2 中,图片生成逻辑可能包含在 Plugin.ContentMeta 或者独立的 Emitter 中。 请尝试注释掉 quartz.config.ts 里的 Plugin.ContentMeta() 看看是否能跑通。

第二步:解决 “Missing index.md” 警告

报错中还有一个警告:content/index.md does not exist。 这是因为你的 content 文件夹是空的。Quartz 需要一个首页。

  1. 进入 content 文件夹。

  2. 新建一个文件名为 index.md

  3. 随便写点内容,例如:

    ---
    title: 我的知识库
    ---
    
    Hello World! 这是我的 Quartz 站点。
    

第三步:再次启动

npx quartz build --serve

代码示例(修改前):

// quartz.config.ts
const config: QuartzConfig = {
  // ...
  plugins: {
    // ...
    emitters: [
      Plugin.AliasRedirects(),
      Plugin.ComponentResources(),
      Plugin.ContentPage(),
      Plugin.FolderPage(),
      Plugin.TagPage(),
      Plugin.ContentIndex(),
      Plugin.NotFoundPage(),
      Plugin.Assets(),
      Plugin.Static(),
      Plugin.Cname(),
      // ↓↓↓↓↓↓ 就是这一行惹的祸 ↓↓↓↓↓↓
      Plugin.CustomOgImages(), // 或者叫 Plugin.OgImage()
    ],
  },
}

修改后(直接注释掉):

      // Plugin.CustomOgImages(), 

启动成功,但是访问后出现404

启动成功,但是访问后出现

启动成功,但是访问后出现404
npx quartz build --serve
 
 Quartz v4.5.2  
 
Cleaned output directory `public` in 6ms
Found 0 input files from `content` in 14ms
Parsed 0 Markdown files in 1ms
Filtered out 0 files in 5μs
 
Warning: you seem to be missing an `index.md` home page file at the root of your `content` folder (`content/index.md does not exist`). This may cause errors when deploying.
Emitted 13 files to `public` in 101ms
Done processing 0 files in 123ms
Started a Quartz server listening at http://localhost:8080
hint: exit with ctrl+c
[404] /
[200] /index.css
[200] /prescript.js
[200] /postscript.js
[200] /static/contentIndex.json
[200] /static/icon.png
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
[404] /
 

问题非常明确,你的终端日志里已经把答案写出来了:

Warning: you seem to be missing an `index.md` home page file at the root of your `content` folder (`content/index.md does not exist`).

这意味着:程序启动成功了,但因为你的 content 文件夹是空的(连首页都没有),所以它只能给你展示 404。

✅ 解决方法

你需要手动创建一个 index.md 文件作为网站的首页。请直接在你的终端里运行下面这行命令(复制并执行):

echo -e "---\ntitle: 首页\n---\n\n# 欢迎来到我的 Quartz 知识库\n这是主页内容。" > content/index.md

或者,你也可以手动操作:

  1. 打开你的项目文件夹。
  2. 进入 content 文件夹。
  3. 新建一个文件,命名为 index.md (注意后缀是 .md)。
  4. 在里面随便写点内容保存。

修复后: Quartz 通常会自动检测到新文件并刷新。如果没有刷新,请在终端按 Ctrl + C 停止服务,然后重新运行 npx quartz build --serve。再次访问 localhost:8080 就正常了。

如何向 Quartz v4 中添加知识库

向 Quartz v4 添加内容非常简单,因为它本质上就是把 Markdown 文件 转换成网页。

你只需要记住一个核心规则:content 文件夹里的所有 .md 文件,都会自动变成网站上的页面。

以下是添加知识库内容的 3 种进阶姿势:


方法一:基础操作 (直接新建文件)

  1. 新建文件: 在 content 文件夹下新建一个 .md 文件,例如 hello-world.md

  2. 添加头部信息 (Frontmatter): 虽然不是必须的,但建议在文件顶部添加 YAML 头部信息,用于定义标题、标签和日期。

    ---
    title: Android Trace 分析技巧  # 网页显示的标题
    date: 2025-12-27           # (可选) 发布日期
    tags: [Android, 性能优化]    # (可选) 标签,生成标签页
    draft: false               # (可选) 如果设为 true,构建时会忽略
    ---
    
    这里是正文内容...
    
  3. 查看效果: 保存文件后,终端里的服务会自动刷新。访问 http://localhost:8080/hello-world 即可看到页面。


方法二:使用 Obsidian 编辑 (强烈推荐 ⭐)

Quartz 的最大魅力在于它和 Obsidian 是绝配。你不需要用代码编辑器写文章,而是直接用 Obsidian 管理你的知识库。

  1. 打开仓库: 启动 Obsidian 选择 “打开本地仓库” (Open folder as vault) 选择你的 content 文件夹(或者整个 Quartz 项目目录)。

  2. 享受双链功能: Quartz 完美支持 Obsidian 的 双向链接 (Wiki Links)

    • 链接文章:输入 [[,Obsidian 会自动补全你库里的其他笔记。Quartz 网页版会自动生成点击跳转,并建立关系图谱

    • 嵌入图片:直接把图片拖进 Obsidian 笔记里。Quartz 构建时会自动处理图片路径。

    示例: 如果你在 index.md 里写了一句 详细分析请参考 [[android-trace]],网页上点击这个链接就会跳转到 content/android-trace.md


方法三:整理目录结构 (分类管理)

你可以随意在 content 里创建文件夹来整理知识。文件夹结构会直接对应 URL 路径。

示例结构:

content/
├── index.md            -> http://localhost:8080/
├── Android/
│   ├── trace.md        -> http://localhost:8080/Android/trace
│   └── binder.md       -> http://localhost:8080/Android/binder
├── Linux/
│   └── kernel.md       -> http://localhost:8080/Linux/kernel
└── images/             -> (存放图片的文件夹)
    └── screenshot.png

核心语法速查

功能Markdown/Obsidian 语法Quartz 网页效果
双向链接[[文件名]][[文件名 | 自定义显示文字]]
图片![[图片.png]] 或 standard ![](./img.png)自动渲染图片
Callout (提示块)> [!info] 提示内容渲染为带有颜色和图标的提示框
思维导图mermaid ... 渲染为交互式图表

下一步建议

你可以试着把你之前关于“Android Trace”的笔记复制进去,然后用 [[ ]] 把它链接到首页 (index.md),看看右侧的 Graph View (关系图) 是如何自动生长的。

端口号修改

修改 Quartz v4 的启动端口号非常简单,你可以通过命令行参数临时修改,或者通过配置文件永久修改。默认端口是 8080

方法一:命令行临时修改 (推荐)

如果你只是这次想换个端口跑(例如 8080 被占用了),直接在启动命令后面加上 --port 参数即可。

示例:使用 8888 端口启动

npx quartz build --serve --port 8888

启动后,访问地址就会变成 http://localhost:8888


方法二:永久修改 (修改 package.json)

如果你希望每次启动都自动使用新端口,不需要每次敲参数,可以修改 package.json 文件里的启动脚本。

  1. 打开项目根目录下的 package.json 文件。
  2. 找到 scripts 部分,通常有一行 "quartz": "npx quartz build --serve"
  3. 在这行命令后面加上 --port 你的端口号

方法二:修改 package.json (永久生效/快捷指令)

为了避免每次都要手动输入长长的命令和端口号,建议在 package.jsonscripts 区域添加一条快捷指令。

1. 打开 package.json

找到 scripts 代码块(在你刚才发的内容里):

  "scripts": {
    "quartz": "./quartz/bootstrap-cli.mjs",
    "docs": "npx quartz build --serve -d docs",
    "check": "tsc --noEmit && npx prettier . --check",
    "format": "npx prettier . --write",
    "test": "tsx --test",
    "profile": "0x -D prof ./quartz/bootstrap-cli.mjs build --concurrency=1"
  },

2. 添加 “dev” 指令

在里面插入一行 "dev" (或者叫 "serve"),指定你想要的端口号(例如 3000)。注意行末要加逗号。

修改后的代码:

  "scripts": {
    "dev": "npx quartz build --serve --port 5000",  // <--- 新增这行,指定端口 5000
    "quartz": "./quartz/bootstrap-cli.mjs",
    "docs": "npx quartz build --serve -d docs",
    "check": "tsc --noEmit && npx prettier . --check",
    // ... 其他保持不变
  },

3. 启动

保存文件后,以后只需要运行以下短命令即可:

npm run dev

常见端口被占用报错

知识库内容可以扩展到其他目录么 比如我本地还有一个 /home/zbc/micode/GeneralAndroid/main/blog的博客目录

想要将外部目录(如 /home/zbc/micode/GeneralAndroid/main/blog)的内容加入到 Quartz 知识库中,最简单且无侵入的方法是使用 软链接 (Symbolic Link)

Quartz 默认只扫描项目根目录下的 content 文件夹。通过软链接,我们可以把外部文件夹“骗”进 content 目录,让 Quartz 以为它就在本地。

✅ 操作步骤

假设你想把那个外部博客目录映射为网站上的 /blog 路径:

1. 进入 content 目录

打开终端,进入你的 Quartz 项目的 content 文件夹:

cd quartz/content

2. 创建软链接

执行以下命令(注意路径要准确):

# ln -s <外部真实路径> <content下的目录名>
ln -s /home/zbc/micode/GeneralAndroid/main/blog myblog

解释:这会在当前目录下创建一个名为 myblog 的快捷方式,它直接指向你那个外部目录。

3. 验证效果

现在,你的文件结构看起来是这样的:

quartz/content/
├── index.md        (你的首页)
└── myblog/         (这是一个软链接 🔗)
    └── ...         (这里面是你外部目录里的所有 md 文件)

4. 重新启动预览

如果服务正在运行,建议 Ctrl + C 停止后重新启动,以确保它能扫描到新目录:

npx quartz build --serve

现在,访问 http://localhost:8080/myblog/ 应该就能看到你那个目录下的内容了。


⚠️ 两个关键注意事项

  1. 外部目录要有 index.md 为了让 http://localhost:8080/myblog/ 这个路径能正常显示,你的外部目录 /home/zbc/micode/GeneralAndroid/main/blog 下面最好有一个 index.md 文件。如果没有,Quartz 可能只会显示一个文件列表或者 404。
  2. 关于图片引用 如果你的外部 Markdown 文件里引用了图片(例如 ![[image.png]]),这些图片也必须能被 Quartz 找到。
    • 情况 A:图片就在那个 blog 目录下。 正常显示,没问题。
    • 情况 B:图片在 blog 目录之外的其他地方。 会裂图
    • 解决办法:你也需要把存放图片的文件夹软链接到 content 目录里。

进阶:如果那个外部目录是一个 Git 仓库

如果你打算用 npx quartz sync 把网站发布到 GitHub Pages,软链接可能会被当作是一个“子模块 (Submodule)”或者纯文本文件处理,导致发布上去是空的。

  • 只在本地看:完全没影响,上面的方法最好用。
  • 要发布到公网:你需要配置 Git 让它跟踪软链接指向的内容(比较麻烦),或者在部署脚本里加一步 cp -r 把文件通过复制的方式“搬”过来,而不是用软链接。

对于本地知识库管理,软链接 (Symbolic Link) 是目前最高效的方案。