The precomputed types meta loader is a Webpack/Turbopack loader that automatically generates comprehensive type documentation for your TypeScript components at build time. Write your components in TypeScript, and the loader extracts props, methods, and type signatures—ready to display in your documentation.
Tip
For the high-level rationale behind this pattern see the Built Factories Pattern.
The loader processes types.ts files that use the createTypesMeta factory pattern, analyzing your TypeScript components and extracting detailed metadata about their APIs. It delegates the actual type processing to loadServerTypesMeta, then injects the precomputed results back into your source code.
Note
The loader works with any
create*function that follows the types meta pattern, not justcreateTypesMeta. You can create custom factory functions usingabstractCreateTypeslikecreateApiReference()orcreateTypeDocs()that return documentation components.
The easiest way to configure this loader is with the withDocsInfra Next.js plugin:
// next.config.mjs
import { withDocsInfra } from '@mui/internal-docs-infra/withDocsInfra';
export default withDocsInfra({
// Automatically includes types.ts loader pattern
});
If you need manual control, add the loader directly to your next.config.mjs:
Note
The Turbopack loader requires Next.js version v15.5 or later (depends on this fix)
/** @type {import('next').NextConfig} */
const nextConfig = {
turbopack: {
rules: {
'./app/**/types.ts': {
as: '*.ts',
loaders: ['@mui/internal-docs-infra/pipeline/loadPrecomputedTypesMeta'],
},
},
},
webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
config.module.rules.push({
test: /\/types\.ts$/,
use: [defaultLoaders.babel, '@mui/internal-docs-infra/pipeline/loadPrecomputedTypesMeta'],
});
return config;
},
};
The loader processes types.ts files that contain createTypesMeta factory functions:
app/
├── components/
│ ├── button/
│ │ ├── types.ts # ← createTypesMeta() processed here
│ │ ├── page.tsx # ← Next.js page that uses the types
│ │ ├── Button.tsx
│ │ └── demos/
│ │ └── basic/
│ │ └── index.ts
│ └── input/
│ ├── types.ts # ← And here
│ ├── page.mdx # ← Or MDX page that uses the types
│ ├── Input.tsx
│ ├── InputLabel.tsx
│ └── demos/
│ └── advanced/
│ └── index.ts
Create a types.ts file with the factory pattern using a descriptive named export:
import { createTypesMeta } from '../createTypesMeta';
import Component from './Component';
export const TypesComponent = createTypesMeta(import.meta.url, Component);
Your page.tsx or page.mdx files can then import and render the component returned by createTypesMeta:
// page.tsx
import { TypesComponent } from './types';
export default function ComponentPage() {
return <TypesComponent />;
}
When a component has multiple parts (like CheckboxRoot and CheckboxIndicator), you can document them all:
import { createMultipleTypes } from '../createTypes';
import { Checkbox } from '@base-ui/react/checkbox';
const types = createMultipleTypes(import.meta.url, Checkbox);
export const TypesCheckboxRoot = types.Root;
export const TypesCheckboxIndicator = types.Indicator;
For debugging or development, you can skip the build-time processing:
export const TypesComponent = createTypesMeta(import.meta.url, Component, {
skipPrecompute: true,
});
Configure the webpack/Turbopack loader with these options:
interface LoaderOptions {
/** Performance tracking and logging options */
performance?: {
/** Enable detailed performance logging */
logging?: boolean;
/** Only log operations exceeding this threshold in milliseconds */
notableMs?: number;
/** Show wrapper measurements in performance logs */
showWrapperMeasures?: boolean;
/** Threshold for notable dependency counts */
significantDependencyCountThreshold?: number;
};
/** Options for formatting types in tables */
formatting?: FormatInlineTypeOptions;
/**
* Directory path for socket and lock files used for IPC between workers.
* Useful for Windows where the default temp directory may not support Unix domain sockets.
* Relative paths are resolved from the project root.
*/
socketDir?: string;
}
Example configuration:
// next.config.mjs
config.module.rules.push({
test: /\/types\.ts$/,
use: [
defaultLoaders.babel,
{
loader: '@mui/internal-docs-infra/pipeline/loadPrecomputedTypesMeta',
options: {
performance: { logging: true, notableMs: 100 },
formatting: { shortTypeUnionPrintWidth: 50, defaultValueUnionPrintWidth: 40 },
socketDir: '.next/cache/docs-infra/types-meta-worker',
},
},
],
});
The loader follows these steps to precompute your type documentation:
Finds your createTypesMeta function call and extracts the component references and options.
Calls loadServerTypesMeta with the parsed factory call, which handles:
Injects the precompute object into your source code with the processed type data.
// Your source before processing
export const TypesButton = createTypesMeta(import.meta.url, Button);
// After processing (simplified)
export const TypesButton = createTypesMeta(import.meta.url, Button, {
precompute: {
exports: {
Button: {
types: [
/* formatted TypesMeta objects */
],
typeNameMap: {
/* flat to dotted name mappings */
},
},
},
singleComponentName: 'Button',
},
});
Adds all discovered TypeScript source files to webpack's watch list for hot reloading.
types.ts files next to their component pagesTypesButtonRootsocketDir for Windows compatibilityloadServerTypesMeta - Core type processing logicabstractCreateTypes - Create custom type factorieswithDocsInfra - Next.js plugin with auto-configuration