散篇笔记适合讲清一个点;架构导读、逐文件剖析这类内容塞进一篇,读者会累,作者也会被迫概括。本册把原先那篇过长的源码导读拆开,按阅读顺序分章——而「系列小册」本身,也是墨栈为这类内容准备的一等公民版块。
读完本册,你应能独立回答:
- 一篇
.mdx(散篇或系列章节)怎样变成线上页面; - 哪些逻辑只在构建期(或服务端)跑,哪些脚本只在浏览器里执行;
- 散篇与系列在目录、索引、路由、进度键上如何分工;
- 改某一功能时,该优先打开哪个文件。
文中少用生硬的外来词堆砌。必要的英文标识(文件名、包名、API)会保留,并在第一次出现时用中文说明含义。
两种内容形态§
| 散篇笔记 | 系列小册 | |
|---|---|---|
| 目录 | content/posts/*.mdx | content/series/{册}/ + series.json + 多章 .mdx |
| 索引 | lib/posts.ts | lib/series.ts(路径辅助在 lib/series-path.ts) |
| 路由 | /posts/[slug] | /series · /series/[series] · /series/[series]/[chapter] |
| 阅读进度键 | 文章路径名 | series/{册}/{章} |
| 适合 | 单点专题、创刊散篇 | 必须循序阅读的长主题 |
两者共用:lib/mdx.tsx 编译链、Prism 高亮、ArticleShell / 进度条 / 本章目录折线。
项目在解决什么问题§
墨栈(INKSTACK)是一个个人技术笔记站:作者用 Markdown/MDX 写稿,站点在构建时把稿子编译成静态 HTML,再用 CDN 或普通静态托管对外发布。
它刻意不做这些事:
- 不做后台、不做数据库、不做评论服务
- 不做运行时拉取文章列表的接口
- 不为了渲染正文而往浏览器塞一整套 Markdown 运行时
它认真做这些事:
- 文首 YAML 元数据 → 列表、标签、SEO 标题
- 代码围栏可多文件切换、可复制、可在沙箱里预览 html/css/js
- 阅读进度条、侧栏目录高亮、「继续阅读」——并且进度按路径键记在浏览器本地
- 系列小册——多章循序内容,与散篇分开存放、分开浏览,章节页为三栏阅读台
技术底座§
| 职责 | 选型 | 在本仓库里主要落在哪 |
|---|---|---|
| 页面框架 | Next.js 16(App Router)+ React 19 | app/ |
| 内容编译 | next-mdx-remote 的 RSC 入口(在服务端/构建期编译) | lib/mdx.tsx |
| 散篇索引 | 扫盘 + gray-matter | lib/posts.ts、content/posts/ |
| 系列索引 | 扫盘 + series.json | lib/series.ts、content/series/ |
| 样式 | Tailwind CSS v4 + 分域手写组件样式 | app/globals.css → app/styles/* |
| 阅读进度状态 | Zustand,并只把历史进度写入 localStorage | components/reading/store.ts |
| 明暗主题 | next-themes,用 data-theme 切换 | app/providers.tsx |
| 代码高亮 | 本地 Prism(不走 CDN) | lib/prism.ts |
RSC:为什么是主轴§
「RSC」即 React Server Components:组件默认在服务端渲染,只有文件顶部声明了 "use client" 的才会打进浏览器 JS 包。
墨栈把正文编译放在服务端一侧,交互控件才标记为客户端组件。读者下载的页面里,没有半行为了「把 Markdown 渲染成 HTML」而存在的 JavaScript——这就是 README 里说的「正文管线零客户端」的准确含义。
下一章先看仓库怎么分层,以及打开散篇 / 系列章节时构建期与浏览器各干什么。