For AI agents: the complete documentation index is available at https://mfdoctor.kevinbeier.com/llms.txt, the full documentation bundle is available at https://mfdoctor.kevinbeier.com/llms-full.txt, and this page is available as Markdown at https://mfdoctor.kevinbeier.com/integrations.md.

Bundler integrations

Choose the adapter owned by the build tool. In every example, the same mfOptions object goes to Module Federation and mfdoctor. Register mfdoctor after the federation plugin so it can inspect the completed output.

  • Vite, Rolldown-integrated Vite, or Vite Plus: @tonoizer/mfdoctor/vite (Rolldown / Vite Plus: partial)
  • Nuxt 3 or Nuxt 4: @tonoizer/mfdoctor/nuxt (partial)
  • Rspack: @tonoizer/mfdoctor/rspack
  • Rsbuild: @tonoizer/mfdoctor/rsbuild
  • Webpack: @tonoizer/mfdoctor/webpack
  • Modern.js: @tonoizer/mfdoctor/modern (partial, App Tools CI emit blocked by lockfile trust policy)

There is no Next.js adapter. @module-federation/nextjs-mf is unsupported (Pages Router only, unmaintained). Prefer Rsbuild or Modern.js. See limitations.

Vite

import { federation } from "@module-federation/vite";
import { federationDoctor } from "@tonoizer/mfdoctor/vite";

const mfOptions = {
  name: "host",
  remotes: {},
};

export default {
  plugins: [federation(mfOptions), federationDoctor({ moduleFederation: mfOptions })],
};

The same adapter covers classic Vite, Rolldown-integrated Vite (rolldown-vite and Vite 8+), and Vite Plus. mfdoctor selects the matching post-emit hook and avoids duplicate analysis when a build exposes more than one lifecycle hook. See Vite integration for lifecycle and configuration details.

A copyable Vite Plus production smoke lives in examples/compatibility/rolldown. The matrix cell stays partial.

Nuxt 3 and Nuxt 4

Register mfdoctor next to the official Module Federation Nuxt module:

import moduleFederationDoctor from "@tonoizer/mfdoctor/nuxt";

const mfOptions = {
  name: "host",
  remotes: {},
};

export default defineNuxtConfig({
  modules: ["@module-federation/nuxt", [moduleFederationDoctor, { moduleFederation: mfOptions }]],
});

mfdoctor uses Nuxt's public vite:extendConfig hook for client and SSR builds. The official Nuxt module still owns Module Federation. If that integration already exposes nuxt.options.moduleFederation.config, you may omit mfdoctor's explicit moduleFederation option.

A copyable local emit cell lives in examples/compatibility/nuxt. It registers @tonoizer/mfdoctor/nuxt the same way and production-builds. It does not pull @module-federation/nuxt while that upstream example stays baseline-blocked.

Rspack

Use this adapter for direct @rspack/core projects:

import { ModuleFederationPlugin } from "@module-federation/enhanced/rspack";
import { moduleFederationDoctorPlugin } from "@tonoizer/mfdoctor/rspack";

const mfOptions = {
  name: "remote",
  exposes: { "./App": "./src/App.tsx" },
};

export default {
  plugins: [
    new ModuleFederationPlugin(mfOptions),
    moduleFederationDoctorPlugin({ moduleFederation: mfOptions }),
  ],
};

Use the Rspack adapter for direct Rspack builds even if the repository also contains Modern.js or Rsbuild apps.

Rsbuild

import { pluginModuleFederation } from "@module-federation/rsbuild-plugin";
import { pluginModuleFederationDoctor } from "@tonoizer/mfdoctor/rsbuild";

const mfOptions = {
  name: "remote",
  exposes: { "./App": "./src/App.tsx" },
};

export default {
  plugins: [
    pluginModuleFederation(mfOptions),
    pluginModuleFederationDoctor({ moduleFederation: mfOptions }),
  ],
};

The Rsbuild adapter runs through onAfterBuild, after Module Federation has written its manifest and entry files.

Webpack

import { ModuleFederationPlugin } from "@module-federation/enhanced/webpack";
import { ModuleFederationDoctorPlugin } from "@tonoizer/mfdoctor/webpack";

const mfOptions = {
  name: "remote",
  exposes: { "./App": "./src/App.tsx" },
};

export default {
  plugins: [
    new ModuleFederationPlugin(mfOptions),
    ModuleFederationDoctorPlugin({ moduleFederation: mfOptions }),
  ],
};

mfdoctor runs in afterEmit, after the enhanced Module Federation plugin has produced the files used as evidence.

Modern.js

Register the Modern.js adapter with @module-federation/modern-js or @module-federation/modern-js-v3:

import { appTools, defineConfig } from "@modern-js/app-tools";
import { moduleFederationPlugin } from "@module-federation/modern-js-v3";
import { moduleFederationDoctorPlugin } from "@tonoizer/mfdoctor/modern";

const mfOptions = {
  name: "remote",
  exposes: { "./App": "./src/App.tsx" },
};

export default defineConfig({
  plugins: [
    appTools(),
    moduleFederationPlugin({ config: mfOptions, ssr: false }),
    moduleFederationDoctorPlugin({ moduleFederation: mfOptions }),
  ],
});

For Modern.js 2, import moduleFederationPlugin from @module-federation/modern-js instead of @module-federation/modern-js-v3.

This adapter composes a post-emit plugin through modifyBundlerChain and records the build as Modern.js. The in-repo compatibility smoke still uses Rspack-under-the-hood. A real @modern-js/app-tools cell cannot enter this lockfile today: current App Tools releases fail trustPolicy: no-downgrade because 2.63.x published npm provenance and later versions dropped it. Support stays partial. The upstream core-demo re-soak remains #130.

For a direct Rspack path inside tools.bundlerChain, use the public Rspack adapter instead:

import { moduleFederationDoctorPlugin } from "@tonoizer/mfdoctor/rspack";

export default defineConfig({
  tools: {
    bundlerChain(chain) {
      chain
        .plugin("module-federation-doctor")
        .use(moduleFederationDoctorPlugin({ moduleFederation: mfOptions }));
    },
  },
});

That path records the bundler as Rspack.

After the build

Every adapter writes project facts below .mf/doctor/. Build all hosts and remotes, then compare them:

mfdoctor workspace

Use the CLI command reference for monorepo roots, CI formats, federation groups, baselines, and runtime correlation. Browse working examples for mixed Vite, Rspack, Rsbuild, and Webpack federations.