Frontend Development 8 min read

Mastering Module Federation with Vite & Vue: A Step‑by‑Step Guide

Learn how to implement Webpack’s Module Federation using Vite and Vue, covering core concepts, advantages over traditional micro‑frontend solutions, detailed setup steps, code examples, and common pitfalls such as dependency conflicts and version mismatches.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Mastering Module Federation with Vite & Vue: A Step‑by‑Step Guide

What is Module Federation

In frontend projects, different teams may have coupled business modules; for example, Team A provides a rich‑text component that Team B also needs.

Traditionally, Team B would copy A’s code into its own project.

Webpack’s Module Federation allows a service to expose modules that other services can load at runtime, enabling dynamic sharing of components.

Vite can also achieve this via the vite-plugin-federation plugin.

Core Advantages of Module Federation

Key benefits include:

Independent deployment : each application can be developed, built, and deployed separately.

Runtime sharing : modules are loaded dynamically at runtime, not bundled at build time.

Version control : specific versions of shared modules can be declared, simplifying dependency management.

Reduced duplicate code : multiple apps can reuse the same functionality.

Compared with micro‑frontend solutions like qiankun, Module Federation offers finer‑grained, on‑demand loading of individual modules.

Implementation Example (Vite + Vue)

Assume we have two Vite projects:

ui-library

: component provider exposing a button component (

SharedButton.vue

).

main-app

: host application that loads the button from

ui-library

at runtime.

<code>shixiaoshi-demo/
├── ui-library/     # Remote module: exposes component
│   ├── src/SharedButton.vue
│   ├── vite.config.js
└── main-app/       # Host project: loads remote component
    ├── src/App.vue
    ├── vite.config.js
</code>

1. Install the federation plugin

<code>npm install vite-plugin-federation --save-dev
</code>

2. Expose the component

<code>&lt;template&gt;
  &lt;button class="shared-btn"&gt;I am a shared button&lt;/button&gt;
&lt;/template&gt;

&lt;script setup&gt;
&lt;/script&gt;

&lt;style scoped&gt;
.shared-btn {
  padding: 10px;
  background-color: teal;
  color: white;
  border: none;
  border-radius: 5px;
}
&lt;/style&gt;
</code>
<code>import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'ui_library',
      filename: 'remoteEntry.js',
      exposes: {
        './SharedButton': './src/SharedButton.vue',
      },
      shared: ['vue'],
    }),
  ],
  build: {
    target: 'esnext',
    minify: false,
    cssCodeSplit: false,
  },
});
</code>

Start the service

<code>npm run dev -- --port=5001
</code>

Remote entry URL:

http://localhost:5001/assets/remoteEntry.js

3. Load the remote component

<code>import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import federation from '@originjs/vite-plugin-federation';

export default defineConfig({
  plugins: [
    vue(),
    federation({
      name: 'main_app',
      remotes: {
        ui_library: 'http://localhost:5001/assets/remoteEntry.js',
      },
      shared: ['vue'],
    }),
  ],
});
</code>
<code>&lt;template&gt;
  &lt;div&gt;
    &lt;h1&gt;Host Application&lt;/h1&gt;
    &lt;RemoteButton /&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import { defineAsyncComponent } from 'vue';
const RemoteButton = defineAsyncComponent(() => import('ui_library/SharedButton'));
&lt;/script&gt;
</code>
<code>npm run dev
</code>

Visit

http://localhost:5173

and you will see the button component from

ui-library

rendered.

Relationship Diagram

<code>main-app (host)
   |
   | -- runtime request --> http://localhost:5001/assets/remoteEntry.js
   |
   | -- load --> SharedButton.vue exposed by ui-library
   |
   | -- use --> rendered as a local component in the host app
</code>

Drawbacks

In practice, Module Federation can encounter issues such as:

Dependency conflicts : if the remote service depends on a specific Vue version that differs from the host’s version, the component may run with the host’s Vue instance, causing unexpected behavior.

State invalidation : remote components that rely on Vuex or Pinia may lose access to the correct store when executed in the host’s context.

Build configuration differences : plugins like unplugin-auto-import used in the remote service may not be present in the host, leading to missing API errors unless the functions are explicitly imported.

Therefore, it is recommended to keep framework versions, build tools, and plugin configurations consistent between host and remote modules, or provide adapter wrappers to isolate contexts.

FrontendJavaScriptmicro-frontendmodule federationVuevite
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.