-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
中文在结尾(Also have Chinese)
I really like the style of
nextra, so I don't want to give it up. If anyone sees my question below, I hope they can provide guidance on how to complete this practice. Thank you very much.
My Environment
- Nextra version:
nextra v4 - My operating system:
Windows 11 - My editor:
Cursor - Node version:
v20.18.2
My Approach to Organizing Article Structure
I use the content directory, located under src.
My Requirements
-
I need a project landing page, accessible via
localhost:3000. This landing page is located atsrc\app\page.tsx. It cannot be written usingmdormdxfiles, as that does not meet my requirements. -
I want to have multiple independent documentation sets, each displayed in the navigation bar. For example:
-
The "Business Plan" in the navigation bar corresponds to
localhost:3000/docs/, which leads to an independent documentation set with various subdirectories. If a folder contains all themdxfiles for this documentation, such asglossary.mdx, it should be accessible vialocalhost:3000/docs/glossary. -
The "Technical Manual" in the navigation bar corresponds to
localhost:3000/tech/, which also leads to an independent documentation set with various subdirectories. If a folder contains all themdxfiles for this documentation, such asapi.mdx, it should be accessible vialocalhost:3000/tech/api.
The conflict arises:
If I use a structure like
app/docs/[[...mdxPath]]/page.jsxand configurecontentDirBasePath: 'docs', how can I implement the matching forlocalhost:3000/techfor my other independent documentation set? -
My Attempts
1. Using Multiple Routes
Actions:
I created the following directory structure:
app/
├── docs/[[...mdxPath]]/page.jsx # Handles /docs/* paths
└── tech/[[...mdxPath]]/page.jsx # Handles /tech/* paths
└── ......
And modified the page.jsx files as follows:
// app/docs/[[...mdxPath]]/page.jsx
import { generateStaticParamsFor, importPage } from 'nextra/pages'
// Specifies 'docs' as the content source
export const generateStaticParams = generateStaticParamsFor('docs')
// Rest of the code remains unchanged...// app/tech/[[...mdxPath]]/page.jsx
import { generateStaticParamsFor, importPage } from 'nextra/pages'
// Specifies 'tech' as the content source
export const generateStaticParams = generateStaticParamsFor('tech')
// Rest of the code remains unchanged...Correspondingly, the content directory structure is organized as:
content/
├── docs/ # Business Plan content
│ ├── index.mdx
│ └── glossary.mdx
└── tech/ # Technical Manual content
├── index.mdx
└── api.mdxModified next.config.mjs:
const withNextra = nextra({
contentDirBasePath: '/' // Keeps the root path configuration
})Results:
The console throws an error:
Bash
Error: Page "/docs/[[...mdxPath]]/page" is missing param "/docs" in "generateStaticParams()", which is required with "output: export" config.
at DevServer.renderToResponseWithComponentsImpl (file://D:\Projects\sanyeyun_docs\node_modules\next\dist\server\base-server.js:1186:49)I didn't know what to do, so I removed the following from next.config.mjs:
const nextConfig = {
// output: 'export', // Removed this line
images: {
unoptimized: true
}
}Restarting the development server still results in the following error:
- error [nextra] Error while loading { pathSegments: [] } Error: Cannot find module './undefined'
at webpackContextResolve (D:\Projects\sanyeyun_docs\.next\server\app\docs\[[...mdxPath]]\page.js:139:11)
at webpackContext (D:\Projects\sanyeyun_docs\.next\server\app\docs\[[...mdxPath]]\page.js:134:11)
at async Page (src\app\docs\[[...mdxPath]]\page.jsx:16:17)
14 | export default async function Page(props) {
15 | const params = await props.params
> 16 | const result = await importPage(params.mdxPath)
| ^
17 | const { default: MDXContent, toc, metadata } = result
18 | return (
19 | <Wrapper toc={toc} metadata={metadata}> {
code: 'MODULE_NOT_FOUND'
}2. Using a Single-Layer Route but Adjusting the Structure in the content Directory
Actions:
- I adjusted the
appdirectory to the following structure:
app/
├── [[...mdxPath]]/page.jsx # [[...mdxPath]] directly under the root
├── page.tsx
├── layout.jsx
├── ......
- And adjusted the structure under the
contentdirectory:
content/
├── docs/ # Business Plan content
│ ├── index.mdx
│ └── glossary.mdx
└── tech/ # Technical Manual content
├── index.mdx
└── api.mdx- And changed the
contentDirBasePathvalue to'/'.
Now, when I try to start the development server, I encounter the following error, which prevents it from starting:
[Error: You cannot define a route with the same specificity as a optional catch-all route ("/" and "/[[...mdxPath]]").]So, I removed src\app\page.tsx and created a new src\content\index.mdx to temporarily replace the landing page.
I created a new src\content\_meta.js with the following content:
export default {
index: {
display: 'hidden',
},
docs: {
type: 'page',
title: 'Business Plan',
display: 'children'
},
tech: {
type: 'page',
title: 'Technical Manual',
display: 'children'
},
}This seems to be very close to what I want, but there are two unacceptable points:
- I no longer have a custom landing page because the landing page is written in
mdx. - If I want to independently configure the
layout.jsxfor thetechfiles in the future, it seems impossible because thecontentdirectory can only parsemdxfiles.
Chinese Version 中文:
我很喜欢
nextra的风格,所以我不想放弃它。如果有人能看到我下面提出的问题,希望能简单指导我怎样完成这个实践。不胜感激。
我的环境
nextra version:nextra v4
我的操作系统:windows11
我的编辑器:cursor
node version:v20.18.2
我选择组织文章结构的方式:
使用 content 目录,并且在 src 下。
我的需求
-
我需要有一个项目的亮点首页,能通过
localhost:3000访问到,首页地址在src\app\page.tsx,首页不能用md或者mdx文件写,因为这达不到我的要求。 -
我不止想拥有一个文档,而是多个独立文档,他们应当分别显示在导航栏。举例:
-
导航栏的“商业计划书”对应
localhost:3000/docs/,点进去以后是一个有各种子目录层级的独立文档。在某个文件夹内存放所有该文档的 mdx 文件,比如在其中存放了glossary.mdx,就可通过localhost:3000/docs/glossary访问。 -
导航栏的“技术手册”对应
localhost:3000/tech/,点进去以后也是一个有各种子目录层级的独立文档。在某个文件夹内存放所有该文档的 mdx 文件,比如存放了api.mdx,就可通过localhost:3000/tech/api访问。
-
冲突点在于:
如果我使用 app/docs/[[...mdxPath]]/page.jsx 这样的结构,并且配置contentDirBasePath: 'docs',那我另一个独立文档又该怎么实现对 localhost:3000/tech 结尾的匹配呢?
我的尝试
1. 采用多重路由
操作:
我创建如下的目录结构:
app/
├── docs/[[...mdxPath]]/page.jsx # 处理 /docs/* 路径
└── tech/[[...mdxPath]]/page.jsx # 处理 /tech/* 路径
└── ......并分别更改其中的 page.jsx :
// app/docs/[[...mdxPath]]/page.jsx
import { generateStaticParamsFor, importPage } from 'nextra/pages'
// 指定使用 'docs' 作为内容源
export const generateStaticParams = generateStaticParamsFor('docs')
// 其余代码保持不变... // app/tech/[[...mdxPath]]/page.jsx
import { generateStaticParamsFor, importPage } from 'nextra/pages'
// 指定使用 'tech' 作为内容源
export const generateStaticParams = generateStaticParamsFor('tech')
// 其余代码保持不变...相应的组织目录结构:
content/
├── docs/ # 商业计划书内容
│ ├── index.mdx
│ └── glossary.mdx
└── tech/ # 技术手册内容
├── index.mdx
└── api.mdx调整next.config.mjs:
const withNextra = nextra({
contentDirBasePath: '/' // 保持根路径配置
})结果:
控制台报错:
Error: Page "/docs/[[...mdxPath]]/page" is missing param "/docs" in "generateStaticParams()", which is required with "output: export" config.
at DevServer.renderToResponseWithComponentsImpl (file://D:\Projects\sanyeyun_docs\node_modules\next\dist\server\base-server.js:1186:49)我不知道该怎么办,于是我删除了next.config.mjs里的以下内容:
const nextConfig = {
- // output: 'export', 删除这行
images: {
unoptimized: true
}
}再次启动开发服务器,还是有如下报错:
- error [nextra] Error while loading { pathSegments: [] } Error: Cannot find module './undefined'
at webpackContextResolve (D:\Projects\sanyeyun_docs\.next\server\app\docs\[[...mdxPath]]\page.js:139:11)
at webpackContext (D:\Projects\sanyeyun_docs\.next\server\app\docs\[[...mdxPath]]\page.js:134:11)
at async Page (src\app\docs\[[...mdxPath]]\page.jsx:16:17)
14 | export default async function Page(props) {
15 | const params = await props.params
> 16 | const result = await importPage(params.mdxPath)
| ^
17 | const { default: MDXContent, toc, metadata } = result
18 | return (
19 | <Wrapper toc={toc} metadata={metadata}> {
code: 'MODULE_NOT_FOUND'
}2. 采用单层路由,但是调整 content 目录里的结构
操作
- 我把 app 目录调整成如下结构:
app/
├── [[...mdxPath]]/page.jsx # 让[[...mdxPath]]直接在根目录
├── page.tsx
├── layout.jsx
├── ......- 并且调整了
content目录下的结构:
content/
├── docs/ # 商业计划书内容
│ ├── index.mdx
│ └── glossary.mdx
└── tech/ # 技术手册内容
├── index.mdx
└── api.mdx- 并且把
contentDirBasePath值更改为'/'。
然后我现在尝试启动开发服务器,发现有报错如下,导致启动不了:
[Error: You cannot define a route with the same specificity as a optional catch-all route ("/" and "/[[...mdxPath]]").] 于是我删除了 src\app\page.tsx ,并且新建了一个 src\content\index.mdx来暂时替代首页。
我新建了 src\content\_meta.js,内容如下:
export default {
index: {
display: 'hidden',
},
docs: {
type: 'page',
title: '商业计划书',
display: 'children'
},
tech: {
type: 'page',
title: '技术手册',
display: 'children'
},
}这次似乎很接近的我想要的样子了,但是有两点的难以接受:
- 我不再有自定义的首页,因为首页是用
mdx写的。 - 如果之后我想独立配置
tech文件的layout.jsx,这似乎就不能实现,因为content目录下似乎只能解析mdx文件。