Webpack loader for processing MDX files into React components
npx @tessl/cli install tessl/npm-mdx-js--loader@3.1.0MDX Loader is a webpack loader for processing MDX files. It compiles MDX (Markdown with JSX) files into React components that can be bundled by webpack, enabling seamless integration of MDX content into webpack-based build systems. The loader compiles MDX files into React components, supporting all features of the MDX compiler including JSX expressions, component imports, and custom syntax extensions.
npm install @mdx-js/loaderThe package exports a single webpack loader as the default export:
// Webpack configuration usage - no direct imports needed
module.exports = {
module: {
rules: [
{
test: /\.mdx?$/,
use: ['@mdx-js/loader']
}
]
}
};/**
* @import {Configuration} from 'webpack'
*/
/** @type {Configuration} */
const webpackConfig = {
module: {
rules: [
{
test: /\.mdx?$/,
use: [
{
loader: '@mdx-js/loader',
options: {
// MDX compiler options
}
}
]
}
]
}
};
export default webpackConfig;/** @type {Configuration} */
const webpackConfig = {
module: {
rules: [
{
test: /\.mdx?$/,
use: [
{
loader: '@mdx-js/loader',
options: {
jsxImportSource: 'preact',
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypeHighlight]
}
}
]
}
]
}
};/** @type {Configuration} */
const webpackConfig = {
module: {
rules: [
{
test: /\.mdx?$/,
use: [
// Note: Webpack runs right-to-left
{loader: 'babel-loader', options: {}},
{
loader: '@mdx-js/loader',
options: {}
}
]
}
]
}
};The loader is designed as a bridge between MDX content and webpack bundling:
index.cjs) is a CommonJS module required by webpacklib/index.js) and dynamically imported@mdx-js/mdx compiler internally via createFormatAwareProcessorsThe main loader function that processes MDX files within webpack's module system.
/**
* Webpack loader for MDX files (CommonJS wrapper)
* @this {LoaderContext<unknown>} Webpack loader context
* @param {string} code - MDX source code
* @returns {undefined} Uses async callback pattern via this.async()
*/
function loader(code);
/**
* Core ESM loader implementation
* @this {LoaderContext<unknown>} Webpack loader context
* @param {string} value - MDX source code
* @param {LoaderContext<unknown>['callback']} callback - Webpack async callback
* @returns {undefined} Calls callback with results
*/
function loader(value, callback);The loader uses webpack's async callback pattern and processes MDX content through the following steps:
this.getOptions()Configuration options that can be passed to the loader via webpack configuration.
/**
* Configuration options for @mdx-js/loader
* Same as CompileOptions from @mdx-js/mdx except for SourceMapGenerator and development
*/
type Options = Omit<CompileOptions, 'SourceMapGenerator' | 'development'>;
interface CompileOptions {
/** File format detection ('detect' is default) */
format?: 'detect' | 'md' | 'mdx' | null | undefined;
/** Whether to keep JSX instead of compiling it away (default: false) */
jsx?: boolean | null | undefined;
/** Where to import automatic JSX runtimes from (default: 'react') */
jsxImportSource?: string | null | undefined;
/** JSX runtime to use (default: 'automatic') */
jsxRuntime?: 'automatic' | 'classic' | null | undefined;
/** Output format (default: 'program') */
outputFormat?: 'function-body' | 'program' | null | undefined;
/** Base URL for import resolution (example: import.meta.url) */
baseUrl?: URL | string | null | undefined;
/** Casing for attribute names (default: 'react') */
elementAttributeNameCase?: 'react' | 'html' | null | undefined;
/** Casing for CSS property names (default: 'dom') */
stylePropertyNameCase?: 'dom' | 'css' | null | undefined;
/** Convert table cell align attributes to CSS styles (default: true) */
tableCellAlignToStyle?: boolean | null | undefined;
/** Markdown file extensions */
mdExtensions?: ReadonlyArray<string> | null | undefined;
/** MDX file extensions */
mdxExtensions?: ReadonlyArray<string> | null | undefined;
/** List of remark (markdown) plugins */
remarkPlugins?: PluggableList | null | undefined;
/** List of rehype (HTML) plugins */
rehypePlugins?: PluggableList | null | undefined;
/** List of recma (JavaScript) plugins */
recmaPlugins?: PluggableList | null | undefined;
/** Options for remark-rehype plugin */
remarkRehypeOptions?: Readonly<RemarkRehypeOptions> | null | undefined;
/** Where to import MDX provider from (example: '@mdx-js/react') */
providerImportSource?: string | null | undefined;
/** @deprecated JSX pragma for classic runtime (default: 'React.createElement') */
pragma?: string | null | undefined;
/** @deprecated JSX fragment for classic runtime (default: 'React.Fragment') */
pragmaFrag?: string | null | undefined;
/** @deprecated JSX import source for classic runtime (default: 'react') */
pragmaImportSource?: string | null | undefined;
}
interface PluggableList extends Array<Pluggable> {}
interface Pluggable extends Array<any> {
0: Plugin;
1?: Options;
}
interface Plugin extends Function {}Key Configuration Notes:
SourceMapGenerator and development options are automatically handled by the loader based on webpack configurationdevelopment is set based on webpack's mode (development vs production)SourceMapGenerator is set when webpack source maps are enabled@mdx-js/mdx CompileOptions are supportedThe loader implements a sophisticated caching system for performance optimization.
/**
* Cache structure for storing compiled processors
* WeakMap keyed by webpack compiler instance, containing Maps of option hashes to processors
*/
const cache = new WeakMap<WebpackCompiler, Map<string, Process>>();
/**
* Generate hash for options to enable caching
* @param {Readonly<Options>} options - Loader configuration options
* @returns {string} Hash string for cache key
*/
function getOptionsHash(options);The caching system:
WeakMap keyed by webpack compiler instance to ensure proper cleanupThe loader integrates with webpack's type system and MDX compiler types:
/**
* Webpack loader context interface
*/
interface LoaderContext<T> {
/** Get loader options with type safety */
getOptions(): T;
/** Webpack compiler instance */
_compiler?: WebpackCompiler;
/** Current file path being processed */
resourcePath: string;
/** Directory context for relative paths */
context: string;
/** Whether source maps are enabled */
sourceMap: boolean;
/** Webpack build mode */
mode: 'development' | 'production';
/** Async callback for returning results */
callback: (error: Error | null, content?: Buffer, sourceMap?: any) => void;
/** Get async callback function */
async(): LoaderContext['callback'];
}
/**
* MDX processor function type
*/
interface Process {
(vfileCompatible: Compatible): Promise<VFile>;
}
/**
* VFile-compatible input types
*/
type Compatible = VFile | Buffer | Uint8Array | string;The loader provides enhanced error messages with file path context:
renderer) are detected and result in helpful error messagesjsxImportSource option