跳转至

新建 Nextra 项目

参考文档: https://nextra.site/docs/docs-theme/start

Nextra 是一个基于 Next.js 的静态站点生成器,专注于文档和博客。它提供了一个简单的界面来创建和管理内容,同时利用 Next.js 的强大功能来构建高性能的网站。

我一直使用 Mkdocs-Material 来搭建自己的个人博客站点,但近期学习 NextJS 框架,决定研究下 Nextra 部署自己的文档站点。另外一个原因就是,Mkdocs-Material 有一部分功能并不开源,而 nextra 完全开源,且采用 MDX 语法,支持在文档中引用 React 组件,从而大大提高了交互性(如果文档需要展示一些交互内容的话,那么强烈推荐这个框架)。

注意

Mkdocs-Material 已经处于维护状态,原作者基于 Mkdocs-Material 开发了一个新的项目 Zensical,有兴趣的同学可以去研究下 Zensical 的使用。

1. 初始化项目

首先我们先使用 Next.JS 初始化一个项目,

cd mononote  # 如果是 Github 项目,建议仓库不包含任何文件
npx create-next-app@latest .

接着安装 Nextra 及其相关依赖:

npm i next react react-dom nextra nextra-theme-docs

执行完成后,可以执行 npm run dev 来启动开发服务,浏览器访问 http://localhost:3000 就可以看到页面了。

使用 turbopack

如果你使用的是 Next.js 13.4 版本以上,建议使用 turbopack 来提升开发体验。可以在 package.json 中将 dev 脚本修改为:

"scripts": {
  "dev": "next dev --turbopack"
}

2. 配置 Nextra

next.config.ts
import nextra from 'nextra'

// Set up Nextra with its configuration
const withNextra = nextra({
  // ... Add Nextra-specific options here
})

// Export the final Next.js config with Nextra included
export default withNextra({
  // ... Add regular Next.js options here
})

3. 添加 mdx-components 文件

在项目根目录下创建一个 mdx-components.tsx 文件,用于定义 MDX 组件:

mdx-components.tsx
import { useMDXComponents as getThemeComponents } from 'nextra-theme-docs' // nextra-theme-blog or your custom theme

// Get the default MDX components
const themeComponents = getThemeComponents()

// Merge components
export function useMDXComponents(components) {
  return {
    ...themeComponents,
    ...components
  }
}

4. 设置搜索

  1. 安装 pagefind 依赖
npm i -D pagefind
  1. 添加 pagefind 配置

Pagefind 索引 .html 文件,因此索引必须在构建应用程序后进行。

package.json
1
2
3
4
5
{
  "scripts": {
    "postbuild": "next build && pagefind --site .next/server/app --output-path public/_pagefind",
  }
}
  1. _pagefind/ 添加到您的 .gitignore 文件以避免提交生成的索引文件。

  2. 验证输出索引:构建并运行 postbuild 脚本后,检查 public/out/ 中是否存在 _pagefind/ 目录。启动您的应用程序并测试搜索栏以确认一切正常。

5. 创建根布局

接下来,我们在 app 目录下创建一个 layout.tsx 文件,用于定义根布局:

app/layout.tsx
import { Footer, Layout, Navbar } from 'nextra-theme-docs'
import { Banner, Head } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import 'nextra-theme-docs/style.css'

export const metadata = {
  // Define your metadata here
  // For more information on metadata API, see: https://nextjs.org/docs/app/building-your-application/optimizing/metadata
}

const banner = <Banner storageKey="some-key">Nextra 4.0 is released 🎉</Banner>
const navbar = (
  <Navbar
    logo={<b>Nextra</b>}
    // ... Your additional navbar options
  />
)
const footer = <Footer>MIT {new Date().getFullYear()} © Nextra.</Footer>

export default async function RootLayout({ children }) {
  return (
    <html
      // Not required, but good for SEO
      lang="en"
      // Required to be set
      dir="ltr"
      // Suggested by `next-themes` package https://github.com/pacocoursey/next-themes#with-app
      suppressHydrationWarning
    >
      <Head
      // ... Your additional head options
      >
        {/* Your additional tags should be passed as `children` of `<Head>` element */}
      </Head>
      <body>
        <Layout
          banner={banner}
          navbar={navbar}
          pageMap={await getPageMap()}
          docsRepositoryBase="https://github.com/shuding/nextra/tree/main/docs"
          footer={footer}
          // ... Your additional layout options
        >
          {children}
        </Layout>
      </body>
    </html>
  )
}

6. 渲染 MDX 文件

有 2 种方式可以渲染 MDX 文件:

  1. 使用 .mdx 后缀的文件,Nextra 默认支持这种文件格式,可以直接渲染。
  2. 使用 content 目录,并将 .mdx 文件放在 content 目录下。

这里推荐第 2 种方式,更方便对文档进行维护和管理。此外,我后续希望给站点添加一个登录功能,所有这里我们新建一个 docs 专门用于 MDX 文档渲染,而 content 目录专门用于存放文档内容。

项目结构
app/
  (auth)/
    page.tsx
  docs/
    [[...mdxPath]]/
      page.jsx
    layout.tsx
content/

7. 运行项目

最后,我们再次执行 npm run dev 来启动开发服务,浏览器访问 http://localhost:3000 就可以看到 Nextra 框架搭建的文档站点了。

8. 文档界面优化

启动后界面有 6 处地方显示需要进行优化,可在 Layout 组件中通过参数进行调整:

  1. 编辑此页
  2. 更新此页
  3. 反馈信息
  4. 复制本页面
  5. 搜索框信息
  6. 暗黑模式的选项
app/docs/layout.tsx
import { Footer, Layout, Navbar, LastUpdated } from 'nextra-theme-docs'
import { Search } from 'nextra/components'
import { getPageMap } from 'nextra/page-map'
import 'nextra-theme-docs/style.css'

const navbar = (
  <Navbar
    logo={<b>Mononote</b>}
    // ... Your additional navbar options
  />
)
const footer = <Footer>MIT {new Date().getFullYear()} © Nextra.</Footer>

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <div>
      <Layout
        navbar={navbar}
        pageMap={await getPageMap()}
        docsRepositoryBase="https://github.com/shuding/nextra/tree/main/docs"
        footer={footer}
        editLink={false}
        feedback={{content: null}}
        lastUpdated={
          <LastUpdated locale='zh'>更新于</LastUpdated>
        }
        copyPageButton={false}
        search={<Search placeholder="搜索" />}
        themeSwitch={{
            dark: '暗黑',
            light: '明亮',
            system: '系统'
        }}
      >
        {children}
      </Layout>
    </div>
  )
}

9. 添加登录功能

安装 shadcn/ui 组件库:

npm install tailwindcss @tailwindcss/postcss postcss
npm install react-hook-form next-auth tailwind-merge @hookform/resolvers zod class-variance-authority @radix-ui/react-slot
npm install lucide-react
npx shadcn@latest add sonner input button label field card input-group

错误

Something went wrong. Please check the error below for more details. If the problem persists, please open an issue on GitHub.

Command failed with exit code 1: npm install sonner next-themes clsx tailwind-merge 'shadcn@latest' class-variance-authority tw-animate-css radix-ui lucide-react

npm error code EEXIST npm error syscall rename npm error path ~/.npm/_cacache/tmp/602eb3c2 npm error dest ~/.npm/_cacache/content-v2/sha512/4c/7e/4e3e6489ec4444e98e0f979fef269e8889b0a4c0de4f072b4a1cd97106736e703be161e09d4be63a22124cb551d92997665b992200ae8bc49f808b2002a7 npm error errno EEXIST npm error Invalid response body while trying to fetch https://registry.npmjs.org/@radix-ui%2freact-toggle-group: EACCES: permission denied, rename '~/.npm/_cacache/tmp/602eb3c2' -> '~/.npm/_cacache/content-v2/sha512/4c/7e/4e3e6489ec4444e98e0f979fef269e8889b0a4c0de4f072b4a1cd97106736e703be161e09d4be63a22124cb551d92997665b992200ae8bc49f808b2002a7' npm error File exists: ~/.npm/_cacache/content-v2/sha512/4c/7e/4e3e6489ec4444e98e0f979fef269e8889b0a4c0de4f072b4a1cd97106736e703be161e09d4be63a22124cb551d92997665b992200ae8bc49f808b2002a7 npm error Remove the existing file and try again, or run npm npm error with --force to overwrite files recklessly. npm error A complete log of this run can be found in: ~/.npm/_logs/2026-03-17T07_40_13_141Z-debug-0.log

这是因为电脑上的 npm 缓存文件权限冲突 导致的,执行 sudo npm cache clean --force

参考文档: