MDX — это расширение Markdown, которое позволяет использовать JSX внутри Markdown-файлов. При интеграции с TypeScript важно правильно настроить проект, чтобы компилятор понимал как JSX, так и синтаксис TypeScript.
Для корректной работы MDX с TypeScript необходимо установить следующие зависимости:
npm install @mdx-js/react @mdx-js/loader typescript ts-loader
@mdx-js/react — обеспечивает рендеринг MDX-компонентов
в React.@mdx-js/loader — загрузчик для Webpack, позволяющий
компилировать MDX в React-компоненты.typescript — ядро TypeScript.ts-loader — интеграция TypeScript с Webpack.Если проект использует Vite, можно использовать
vite-plugin-mdx вместо ts-loader для
упрощённой интеграции.
Создание файла tsconfig.json с правильными настройками
критично для корректного распознавания MDX:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"lib": ["DOM", "ESNext"],
"jsx": "react-jsx",
"moduleResolution": "node",
"allowJs": true,
"checkJs": false,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true
},
"include": ["src/**/*", "**/*.mdx"],
"exclude": ["node_modules"]
}
Ключевые моменты:
jsx: "react-jsx" — использование новой трансформации
JSX, поддерживаемой React 17+.include: ["**/*.mdx"] — обязательно добавление
MDX-файлов, иначе TypeScript их не увидит.skipLibCheck: true — ускоряет сборку, пропуская
проверку типов в сторонних библиотеках.TypeScript не понимает синтаксис MDX по умолчанию. Для корректной
типизации создаётся файл с декларациями типов, например,
src/types/mdx.d.ts:
declare module "*.mdx" {
import { ComponentType, ReactElement } from "react";
const MDXComponent: ComponentType<{ [key: string]: any }>;
export default MDXComponent;
}
Это позволит импортировать MDX-файлы как React-компоненты:
import Content from './content.mdx';
function App() {
return ;
}
В Webpack конфигурации нужно объединить ts-loader и
@mdx-js/loader:
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.mdx$/,
use: [
{
loader: 'babel-loader',
options: { presets: ['@babel/preset-react'] }
},
'@mdx-js/loader'
]
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.jsx', '.mdx']
}
};
Особенности:
babel-loader для
JSX-трансформации, затем @mdx-js/loader для MDX..mdx добавляются в
resolve.extensions для корректного импорта без указания
расширений.Для проектов на Vite используется плагин
vite-plugin-mdx:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import mdx from 'vite-plugin-mdx';
export default defineConfig({
plugins: [react(), mdx()],
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.mdx']
}
});
TypeScript конфигурация аналогична Webpack, включая
include для MDX-файлов и декларации типов.
MDX-файлы можно линтить с помощью eslint-plugin-mdx. В
.eslintrc.js добавляется:
module.exports = {
extends: [
'plugin:mdx/recommended',
'eslint:recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/recommended'
],
settings: { react: { version: 'detect' } },
overrides: [
{
files: ['*.mdx'],
parser: '@typescript-eslint/parser'
}
]
};
Это обеспечивает поддержку TypeScript и JSX внутри MDX при проверке кода.
MDX часто использует общие React-компоненты. В TypeScript важно
корректно типизировать MDXProvider:
import { MDXProvider } from '@mdx-js/react';
import CustomHeading from './components/CustomHeading';
const components = {
h1: CustomHeading
};
function App({ children }: { children: React.ReactNode }) {
return {children} ;
}
Типизация компонентов позволяет TypeScript проверять правильность пропсов для элементов, заменяемых через MDX.
Для оптимизации загрузки можно использовать динамический импорт:
import { lazy, Suspense } from 'react';
const DynamicContent = lazy(() => import('./content.mdx'));
function App() {
return (
Загрузка... TypeScript корректно понимает тип MDXComponent благодаря
ранее созданной декларации.