introduction

MDX是markdown的超级让你能够直接在markdown文件中编写 JSX,它是一种有用的方式去增加动态交互能力,并且在你的内容中内嵌组件 …帮助你引导页面到现实生活 …

Next.js 支持MDX(通过大量不同的含义),这里罗列了一些方式能够集成MDX到Next.js 项目中 …

为什么使用MDX

在markdown中写作是一种直观的方式进行内容编写,它简洁的语法,一旦适配,能够让你写入同时具有超强可读性和可维护性的内容,因为你能够在markdown中使用HTML元素,这样当装饰你的markdown 页面的时候你能够获得创新 …

然而,由于markdown 本质上是静态内容,你不能基于用户的交互性创建动态内容.. 这里MDX它携带了一种能力让你能够创建直接并在标记中使用React 组件,这打开了更多可能性(当构建具有交互性页面) …

MDX 插件

内部MDX使用备注和重新炒作???, 备注是一个markdown 处理器(由插件生态系统支持的),这个插件生态系统能够让我们解析代码,转换HTML元素,改变语法,提取前置物以及更多 …

rehype 是一个HTML处理器,同样是插件生态系统提供支持的,类似于remark,这些插件能够让你维护,清理,编译以及配置所有类型的数据、元素、内容 ..

为了使用一个来自remark或者rehype的插件,你需要增加它们到MDX 包配置 …

next/mdx

这个@next/mdx包配置在next.config.js文件中,它的资源数据来源于本地文件,允许你使用.mdx扩展创建页面,直接使用在/pages目录中 …

在Next.js 中配置@next/mdx

以下步骤罗列了如何在Next.js 项目中配置next/mdx

  • 安装需要的包
  1. npm install @next/mdx @mdx-js/loader
  • 确保这些包存在且配置去支持顶级的.mdx页面,以下增加了一个options对象key 允许我们传递插件 ..
  1. // next.config.js
  2. const withMDX = require('@next/mdx')({
  3. extension: /\.mdx?$/,
  4. options: {
  5. remarkPlugins: [],
  6. rehypePlugins: [],
  7. },
  8. })
  9. module.exports = withMDX({
  10. pageExtensions: ['js', 'jsx', 'md', 'mdx'],
  11. })
  • /pages中创建一个新的MDX 页面
  1. - /pages
  2. - my-mdx-page.mdx
  3. - package.json

使用组件,布局以及自定义元素

现在我能够直接在MDX页面中导入React组件 ..

  1. import { MyComponent } from 'my-components'
  2. # My MDX page
  3. This is a list in markdown:
  4. - One
  5. - Two
  6. - Three
  7. Checkout my React component:
  8. <MyComponent/>

前置器

前置器是一个YAML (类似于 key/value 键值对能够用来存储一个页面的数据) … @next/mdx默认并没有支持前置器(尽管这里存在许多能够增加前置器到你的MDX内容的解决方案,例如 gray-matter) ….

为了使用@next/mdx访问页面的元数据,你能够在.mdx文件中暴露一个元数据对象 …

  1. export const meta = {
  2. author: 'Rich Haines'
  3. }
  4. # My MDX page

例如

  1. ==
  2. ..... metadata
  3. ==

这些 需要通过前置器进行解析 …

布局

为了增加布局到MDX页面中,创建一个新的组件并导入它到MDX 页面中,然后你能够在布局组件中包装这个MDX 页面 …

  1. import { MyComponent, MyLayoutComponent } from 'my-components'
  2. export const meta = {
  3. author: 'Rich Haines'
  4. }
  5. # My MDX Page with a Layout
  6. This is a list in markdown:
  7. - One
  8. - Two
  9. - Three
  10. Checkout my React component:
  11. <MyComponent/>
  12. export default = ({ children }) => <MyLayoutComponent meta={meta}>{children}</MyLayoutComponent>

可以看到这种写法有一点怪异:

并没有将自己传入,而是通过children 属性进行布局渲染 …

自定义元素

使用markdown 令人愉快的一个方面是,它能够映射到HTML元素,能够快速编写且非常直观 …

  1. # H1 heading
  2. ## H2 heading
  3. This is a list in markdown:
  4. - One
  5. - Two
  6. - Three

然后会生成以下内容

  1. <h1>H1 heading</h1>
  2. <h2>H2 heading</h2>
  3. <p>This is a list in markdown:</p>
  4. <ul>
  5. <li>One</li>
  6. <li>Two</li>
  7. <li>Three</li>
  8. </ul>

如果你想要装饰你自己的元素让它有一种另类的感觉,你能够通过短代码进行传递,这些可以是你自己的自定义组件然后映射到HTML元素上,为了这样做,你需要使用MDXProvider并传递一个组件对象作为属性,组件对象中的每一个对象key 都可以映射为HTML元素名 …

例如:

  1. // pages/index.js
  2. import { MDXProvider } from '@mdx-js/react'
  3. import Image from 'next/image'
  4. import { Heading, Text, Pre, Code, Table } from 'my-components'
  5. const ResponsiveImage = (props) => (
  6. <Image alt={props.alt} layout="responsive" {...props} />
  7. )
  8. const components = {
  9. img: ResponsiveImage,
  10. h1: Heading.H1,
  11. h2: Heading.H2,
  12. p: Text,
  13. code: Pre,
  14. inlineCode: Code,
  15. }
  16. export default function Post(props) {
  17. return (
  18. <MDXProvider components={components}>
  19. <main {...props} />
  20. </MDXProvider>
  21. )
  22. }

帮助链接