MDX
Markdown est un langage de balisage léger utilisé pour formater du texte. Il vous permet d'écrire en utilisant une syntaxe en texte brut et de le convertir en HTML structurellement valide. Il est couramment utilisé pour écrire du contenu sur des sites web et des blogs.
Vous écrivez...
I **love** using [Next.js](https://nextjs.org/)
Sortie :
<p>I <strong>love</strong> using <a href="https://nextjs.org/">Next.js</a></p>
MDX est un sur-ensemble de markdown qui vous permet d'écrire du JSX directement dans vos fichiers markdown. C'est une manière puissante d'ajouter de l'interactivité dynamique et d'intégrer des composants React dans votre contenu.
Next.js peut prendre en charge à la fois le contenu MDX local dans votre application et les fichiers MDX distants récupérés dynamiquement sur le serveur. Le plugin Next.js gère la transformation du markdown et des composants React en HTML, y compris la prise en charge de l'utilisation dans les composants serveur (par défaut dans App Router).
@next/mdx
Le package @next/mdx
est utilisé pour configurer Next.js afin qu'il puisse traiter le markdown et MDX. Il récupère les données à partir de fichiers locaux, vous permettant de créer des pages avec une extension .mdx
, directement dans vos répertoires /pages
ou /app
.
Voyons comment configurer et utiliser MDX avec Next.js.
Premiers pas
Installez les packages nécessaires pour afficher MDX :
npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx
Mettez à jour le fichier next.config.js
à la racine de votre projet pour le configurer pour utiliser MDX :
const withMDX = require('@next/mdx')()
/** @type {import('next').NextConfig} */
const nextConfig = {
// Configurez `pageExtensions` pour inclure les fichiers MDX
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
// Optionnellement, ajoutez toute autre configuration Next.js ci-dessous
}
module.exports = withMDX(nextConfig)
Ensuite, créez une nouvelle page MDX dans le répertoire /pages
:
votre-projet
├── pages
│ └── ma-page-mdx.mdx
└── package.json
Maintenant, vous pouvez utiliser le markdown et importer des composants React directement dans votre page MDX :
import { MonComposant } from 'mes-composants'
# Bienvenue sur ma page MDX !
Ceci est du texte en **gras** et _italique_.
Voici une liste en markdown :
- Un
- Deux
- Trois
Découvrez mon composant React :
<MonComposant />
Naviguer vers la route /ma-page-mdx
devrait afficher votre MDX rendu.
MDX distant
Si vos fichiers ou contenu markdown/MDX se trouvent ailleurs, vous pouvez les récupérer dynamiquement sur le serveur. Ceci est utile pour le contenu stocké dans un dossier local séparé, un CMS, une base de données ou tout autre endroit.
Il existe deux packages communautaires populaires pour récupérer du contenu MDX :
Bon à savoir : Veuillez procéder avec prudence. MDX est compilé en JavaScript et exécuté sur le serveur. Vous ne devez récupérer du contenu MDX qu'à partir d'une source de confiance, sinon cela peut conduire à une exécution de code à distance (RCE).
L'exemple suivant utilise next-mdx-remote
:
import { serialize } from 'next-mdx-remote/serialize'
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
interface Props {
mdxSource: MDXRemoteSerializeResult
}
export default function PageMdxDistante({ mdxSource }: Props) {
return <MDXRemote {...mdxSource} />
}
export async function getStaticProps() {
// Texte MDX - peut provenir d'un fichier local, d'une base de données, d'un CMS, d'une requête fetch, etc.
const res = await fetch('https:...')
const mdxText = await res.text()
const mdxSource = await serialize(mdxText)
return { props: { source: mdxSource } }
}
import { serialize } from 'next-mdx-remote/serialize'
import { MDXRemote } from 'next-mdx-remote'
export default function PageMdxDistante({ mdxSource }) {
return <MDXRemote {...mdxSource} />
}
export async function getStaticProps() {
// Texte MDX - peut provenir d'un fichier local, d'une base de données, d'un CMS, d'une requête fetch, etc.
const res = await fetch('https:...')
const mdxText = await res.text()
const mdxSource = await serialize(mdxText)
return { props: { source: mdxSource } }
}
Naviguer vers la route /ma-page-mdx-distante
devrait afficher votre MDX rendu.
Mises en page
Pour partager une mise en page autour des pages MDX, créez un composant de mise en page :
export default function MiseEnPageMdx({ children }: { children: React.ReactNode }) {
// Créez ici toute mise en page ou style partagé
return <div style={{ color: 'blue' }}>{children}</div>
}
export default function MiseEnPageMdx({ children }) {
// Créez ici toute mise en page ou style partagé
return <div style={{ color: 'blue' }}>{children}</div>
}
Ensuite, importez le composant de mise en page dans la page MDX, encapsulez le contenu MDX dans la mise en page et exportez-le :
import MiseEnPageMdx from '../components/mise-en-page-mdx'
# Bienvenue sur ma page MDX !
export default function PageMDX({ children }) {
return <MiseEnPageMdx>{children}</MiseEnPageMdx>;
}
Plugins Remark et Rehype
Vous pouvez éventuellement fournir des plugins remark
et rehype
pour transformer le contenu MDX.
Par exemple, vous pouvez utiliser remark-gfm
pour prendre en charge GitHub Flavored Markdown.
Comme l'écosystème remark
et rehype
est uniquement ESM, vous devrez utiliser next.config.mjs
comme fichier de configuration.
import remarkGfm from 'remark-gfm'
import createMDX from '@next/mdx'
/** @type {import('next').NextConfig} */
const nextConfig = {
// Configurez `pageExtensions` pour inclure les fichiers MDX
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
// Optionnellement, ajoutez toute autre configuration Next.js ci-dessous
}
const withMDX = createMDX({
// Ajoutez ici les plugins markdown souhaités
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [],
},
})
// Fusionnez la configuration MDX avec la configuration Next.js
export default withMDX(nextConfig)
Frontmatter
Le frontmatter est une paire clé/valeur de type YAML qui peut être utilisée pour stocker des données sur une page. @next/mdx
ne prend pas en charge le frontmatter par défaut, bien qu'il existe de nombreuses solutions pour ajouter du frontmatter à votre contenu MDX, telles que :
Pour accéder aux métadonnées de la page avec @next/mdx
, vous pouvez exporter un objet meta depuis le fichier .mdx
:
export const meta = {
author: 'John Doe',
}
# Ma page MDX
Éléments personnalisés
L'un des aspects agréables de l'utilisation du markdown est qu'il correspond aux éléments HTML
natifs, rendant l'écriture rapide et intuitive :
Voici une liste en markdown :
- Un
- Deux
- Trois
Ce qui génère le HTML
suivant :
<p>Voici une liste en markdown :</p>
<ul>
<li>Un</li>
<li>Deux</li>
<li>Trois</li>
</ul>
Lorsque vous souhaitez styliser vos propres éléments pour une apparence personnalisée de votre site web ou application, vous pouvez utiliser des shortcodes. Ce sont vos propres composants personnalisés qui correspondent aux éléments HTML
.
Pour ce faire, créez un fichier mdx-components.tsx
à la racine de votre application (le dossier parent de pages/
ou src/
) et ajoutez des éléments personnalisés :
import type { MDXComponents } from 'mdx/types'
import Image from 'next/image'
// Ce fichier vous permet de fournir des composants React personnalisés
// à utiliser dans les fichiers MDX. Vous pouvez importer et utiliser n'importe quel
// composant React que vous souhaitez, y compris des styles en ligne,
// des composants d'autres bibliothèques, et plus encore.
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
// Permet de personnaliser les composants intégrés, par exemple pour ajouter du style.
h1: ({ children }) => <h1 style={{ fontSize: '100px' }}>{children}</h1>,
img: (props) => (
<Image
sizes="100vw"
style={{ width: '100%', height: 'auto' }}
{...props}
/>
),
...components,
}
}
import Image from 'next/image'
// Ce fichier vous permet de fournir des composants React personnalisés
// à utiliser dans les fichiers MDX. Vous pouvez importer et utiliser n'importe quel
// composant React que vous souhaitez, y compris des styles en ligne,
// des composants d'autres bibliothèques, et plus encore.
export function useMDXComponents(components) {
return {
// Permet de personnaliser les composants intégrés, par exemple pour ajouter du style.
h1: ({ children }) => <h1 style={{ fontSize: '100px' }}>{children}</h1>,
img: (props) => (
<Image
sizes="100vw"
style={{ width: '100%', height: 'auto' }}
{...props}
/>
),
...components,
}
}
Approfondissement : Comment transformer le markdown en HTML ?
React ne comprend pas nativement le markdown. Le texte brut markdown doit d'abord être transformé en HTML. Cela peut être accompli avec remark
et rehype
.
remark
est un écosystème d'outils autour du markdown. rehype
est le même, mais pour HTML. Par exemple, l'extrait de code suivant transforme le markdown en HTML :
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeSanitize from 'rehype-sanitize'
import rehypeStringify from 'rehype-stringify'
main()
async function main() {
const file = await unified()
.use(remarkParse) // Convertit en AST markdown
.use(remarkRehype) // Transforme en AST HTML
.use(rehypeSanitize) // Nettoie l'entrée HTML
.use(rehypeStringify) // Convertit l'AST en HTML sérialisé
.process('Hello, Next.js!')
console.log(String(file)) // <p>Hello, Next.js!</p>
}
L'écosystème remark
et rehype
contient des plugins pour la coloration syntaxique, les liens vers les titres, la génération d'une table des matières, et plus encore.
Lorsque vous utilisez @next/mdx
comme montré ci-dessus, vous n'avez pas besoin d'utiliser remark
ou rehype
directement, car cela est géré pour vous. Nous le décrivons ici pour une meilleure compréhension de ce que fait le package @next/mdx
en arrière-plan.
Utilisation du compilateur MDX basé sur Rust (Expérimental)
Next.js prend en charge un nouveau compilateur MDX écrit en Rust. Ce compilateur est encore expérimental et n'est pas recommandé pour une utilisation en production. Pour utiliser le nouveau compilateur, vous devez configurer next.config.js
lorsque vous le passez à withMDX
:
module.exports = withMDX({
experimental: {
mdxRs: true,
},
})