Why NextWhy Next
返回列表
💻 开发阅读约 2 分钟

用 Next.js 从零搭一个 MDX 博客 - 这个博客就是这么做的

不用 CMS,只靠 Markdown 文件就能运转的博客,用 Next.js 16 App Router 搭建的全过程。目录结构、MDX 配置、SEO,全部按实际代码流程整理。

核心摘要

把文章以 .mdx 文件放在 src/content/posts 下,用 @next/mdx 渲染,不需要 CMS 博客也能跑起来。文件即 URL,用 meta export 代替 frontmatter 来生成列表和元数据。

目录

你现在读的这个博客,既没有数据库,也没有后台管理界面。每篇文章就是一个 Markdown 文件。怎么做的,我原样公开。

为什么选文件方案

博客工具很多,但对独立开发者来说,大部分都太重了。

  • CMS: 附带管理界面、对接工作和费用
  • Notion 集成: 方便,但在渲染、速度、自定义上会卡壳
  • Markdown 文件: 文章和代码一起进版本管理,免费,git push 就是发布

我选了第三种。因为摩擦最小。

目录结构

只看核心的话,长这样。

src/
├── app/
│   ├── page.tsx              # 홈 - 글 목록
│   ├── posts/[slug]/page.tsx # 글 상세
│   └── sitemap.ts            # /sitemap.xml
├── content/posts/*.mdx       # ← 글은 여기에만 추가
└── lib/posts.ts              # 목록·메타 로딩

文件名直接就是 URL。hello.mdx 会以 /posts/hello 打开。

MDX 配置

在 App Router 里用 MDX,要接上 @next/mdx。Next 16 默认使用 Turbopack,所以 remark/rehype 插件必须以字符串名称传入(不能传函数引用)。

const withMDX = createMDX({
  options: {
    remarkPlugins: ["remark-gfm"],   // 표·취소선 지원
    rehypePlugins: ["rehype-slug"],  // 제목 앵커
  },
})

用 meta export 代替 frontmatter

通常我们在 Markdown 顶部的 --- 块(frontmatter)里写标题和日期,但 MDX 能容纳 JavaScript,所以有更干净的做法。直接 export 一个对象就行。

export const meta = {
  title: "글 제목",
  date: "2026-07-06",
  category: "dev",
}

## 본문 시작

列表页把每个文件动态 import 进来,只读这个 meta

const mod = await import(`@/content/posts/${slug}.mdx`)
return mod.meta   // 본문 렌더 없이 메타만

不需要解析库,也不需要单独的索引。

SEO 从第一天就要有

如果博客的目的是获取流量,SEO 就不该留到以后,而要从一开始就做。我给每篇文章配了元数据、Open Graph、JSON-LD 结构化数据,再加上 sitemap.xmlrobots.txtrss.xml,全部作为默认配置铺好了。这部分下一篇文章再细讲。

小结

  • 文章就是一个 .mdx 文件,文件名即 URL
  • @next/mdx + 字符串形式的插件(Turbopack)
  • export const meta 代替 frontmatter
  • SEO 从第一个 commit 就开始

照着这个结构,你的博客 30 分钟也能上线。我正是用这种方式,持续记录着 今日海浪 这类产品背后的故事。

常见问题

为什么用 MDX 文件而不是 CMS?

文章和代码一起进版本管理,完全免费,部署即发布,对独立开发者来说摩擦最小。图片、代码、组件也都能自由嵌入。

没有 frontmatter,怎么生成文章列表?

在每个 .mdx 顶部 export 一个 meta 对象,列表页动态 import 文件、只读取这个 meta 即可。不需要额外的解析库。

相关文章