npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@unidev-hub/mfe-toolkit

v0.1.1

Published

Toolkit for micro-frontend architecture integration

Readme

@unidev-hub/mfe-toolkit

npm version License TypeScript

A comprehensive toolkit for micro-frontend (MFE) architecture integration in React applications.

📚 Table of Contents

✨ Features

  • 🧩 MFE Integration Components: Easily integrate micro-frontends with consistent loading and error handling
  • 🔄 Cross-MFE Communication: Event bus for seamless communication between MFEs
  • 🌐 Shared State: Share state between MFEs with React-like APIs
  • 🧭 Navigation Utilities: Handle navigation across MFE boundaries
  • 📦 MFE Registry: Centralized registry for all MFEs in your application
  • ⚠️ Error Handling: Specialized error boundaries for MFEs
  • 🔌 Module Federation Support: First-class support for Webpack Module Federation

🔧 Installation

NPM

npm install @unidev-hub/mfe-toolkit react react-dom react-router-dom @mantine/core

Yarn

yarn add @unidev-hub/mfe-toolkit react react-dom react-router-dom @mantine/core

PNPM

pnpm add @unidev-hub/mfe-toolkit react react-dom react-router-dom @mantine/core

🚀 Quick Start

1. Set up the MFE Communication Provider

First, set up the MFE Communication Provider in your shell application:

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { MantineProvider } from '@mantine/core';
import { MfeCommunicationProvider } from '@unidev-hub/mfe-toolkit';

function App() {
  return (
          <MantineProvider>
            <BrowserRouter>
              <MfeCommunicationProvider
                      shellName="my-app-shell"
                      shellVersion="1.0.0"
                      initialRegistry={{
                        products: {
                          name: 'products',
                          scope: 'products',
                          module: 'ProductsApp'
                        },
                        vendors: {
                          name: 'vendors',
                          scope: 'vendors',
                          module: 'VendorsApp'
                        }
                      }}
              >
                <YourAppContent />
              </MfeCommunicationProvider>
            </BrowserRouter>
          </MantineProvider>
  );
}

2. Load MFEs using MfeContainer

Use the MfeContainer component to load and integrate micro-frontends:

import React from 'react';
import { Routes, Route } from 'react-router-dom';
import { MfeContainer } from '@unidev-hub/mfe-toolkit';

function AppRoutes() {
  return (
          <Routes>
            <Route path="/" element={<Dashboard />} />

            <Route
                    path="/products/*"
                    element={
                      <MfeContainer
                              name="products"
                              module="ProductsApp"
                              onError={(err) => console.error("Products MFE failed to load:", err)}
                      />
                    }
            />

            <Route
                    path="/vendors/*"
                    element={
                      <MfeContainer
                              name="vendors"
                              module="VendorsApp"
                      />
                    }
            />
          </Routes>
  );
}

3. Communicate Between MFEs

Use the event bus to communicate between MFEs:

// In the Products MFE
import { useMfeEvents } from '@unidev-hub/mfe-toolkit';

function ProductDetail({ product }) {
  const { emit } = useMfeEvents('products');

  const addToCart = () => {
    emit('cart:add-item', {
      id: product.id,
      name: product.name,
      price: product.price
    });
  };

  return (
          <div>
            <h2>{product.name}</h2>
            <button onClick={addToCart}>Add to Cart</button>
          </div>
  );
}

// In the Cart MFE
import { useMfeEvents } from '@unidev-hub/mfe-toolkit';

function Cart() {
  const [items, setItems] = useState([]);
  const { on } = useMfeEvents('cart');

  useEffect(() => {
    const unsubscribe = on('cart:add-item', (product) => {
      setItems(prev => [...prev, product]);
    });

    return unsubscribe;
  }, [on]);

  return (
          <div>
            <h2>Cart ({items.length} items)</h2>
            {/* Render cart items */}
          </div>
  );
}

4. Share State Between MFEs

Use the shared state to share data between MFEs:

// In the User MFE
import { useMfeState } from '@unidev-hub/mfe-toolkit';

function UserProfile() {
  const [user, setUser] = useMfeState('user', 'currentUser', null);

  useEffect(() => {
    // Load user data
    api.getUser().then(userData => {
      setUser(userData);
    });
  }, []);

  return (
          <div>
            {user ? (
                    <div>
                      <h2>{user.name}</h2>
                      <p>{user.email}</p>
                    </div>
            ) : (
                    <div>Loading user...</div>
            )}
          </div>
  );
}

// In any other MFE
import { useMfeStateValue } from '@unidev-hub/mfe-toolkit';

function UserGreeting() {
  const user = useMfeStateValue('user', 'currentUser');

  return (
          <div>
            {user ? `Hello, ${user.name}!` : 'Welcome, Guest!'}
          </div>
  );
}

🧠 Core Concepts

Micro-Frontend Architecture

This toolkit is designed to support a micro-frontend architecture where:

  1. A Shell Application serves as the container for multiple micro-frontends
  2. Micro-Frontends (MFEs) are independent applications that integrate with the shell
  3. MFEs can communicate with each other and the shell through events and shared state
  4. MFEs can be loaded dynamically at runtime

Communication Patterns

The toolkit supports several communication patterns:

  1. Event-based: Using the event bus for loose coupling between MFEs
  2. Shared State: For more direct state sharing with React-like APIs
  3. Context-based: For global context shared across MFEs

Module Federation

The toolkit is designed to work with Webpack Module Federation, which allows:

  1. Dynamic loading of MFEs at runtime
  2. Shared dependencies between MFEs
  3. Independent deployment of MFEs

📦 Components

MfeContainer

A wrapper component that handles loading and rendering micro-frontends:

<MfeContainer
        name="products"         // Name of the MFE (must match registry entry)
        module="ProductsApp"    // Module to load from the MFE
        mfeProps={{             // Props to pass to the MFE
          theme: 'light',
          showFilters: true
        }}
        showLoading={true}      // Whether to show loading indicator
        onError={(err) => {     // Handler for load errors
          console.error(err);
        }}
        onLoad={() => {         // Handler for successful loads
          console.log('MFE loaded successfully');
        }}
/>

MfeErrorBoundary

An error boundary specialized for MFEs:

<MfeErrorBoundary
        name="products"
        fallbackComponent={<CustomErrorUI />}
        onError={(error, info) => {
          // Report error to monitoring service
        }}
        allowRetry={true}
>
  <YourMfeComponent />
</MfeErrorBoundary>

MfeCommunicationProvider

The main provider that sets up communication between MFEs:

<MfeCommunicationProvider
        shellName="my-app-shell"
        shellVersion="1.0.0"
        initialRegistry={{
          // MFE configurations
        }}
>
  <YourAppContent />
</MfeCommunicationProvider>

🪝 Hooks

useMfeEvents

Hook for event-based communication between MFEs:

const { emit, on, off, getHistory } = useMfeEvents('my-mfe');

// Emit an event
emit('user:login', { id: 123, name: 'John' });

// Listen for events
useEffect(() => {
  const unsubscribe = on('cart:updated', (cartData) => {
    // Handle cart update
  });

  return unsubscribe; // Clean up on unmount
}, []);

useMfeState

Hook for shared state between MFEs (similar to React's useState):

const [value, setValue] = useMfeState('namespace', 'key', initialValue);

// Update the value (all MFEs using this state will be updated)
setValue(newValue);

// Functional updates are supported
setValue(prev => prev + 1);

useMfeNavigation

Hook for navigation across MFE boundaries:

const { navigateTo, goBack, onRouteChange } = useMfeNavigation('my-mfe');

// Navigate to another route
navigateTo('/products/123');

// Listen for route changes
useEffect(() => {
  const unsubscribe = onRouteChange((route) => {
    console.log('Route changed:', route.pathname);
  });

  return unsubscribe;
}, []);

useMfeContext

Hook for accessing global context shared between MFEs:

const { setContextValue, getContextValue, useContextState } = useMfeContext();

// Set a context value
setContextValue('theme', 'dark');

// Get a context value
const theme = getContextValue('theme', 'light'); // Default to 'light'

// Use context with state updates (React-like API)
const [user, setUser] = useContextState('currentUser', null);

useMfeRegistry

Hook for accessing and managing the MFE registry:

const {
  registerMfe,
  unregisterMfe,
  getMfeConfig,
  isRegistered
} = useMfeRegistry();

// Register a new MFE
registerMfe({
  name: 'new-mfe',
  scope: 'new-mfe',
  module: 'NewMfeApp'
});

// Check if an MFE is registered
if (isRegistered('products')) {
  // Use the products MFE
}

📡 Communication

EventBus

The core event bus for communication between MFEs:

import { EventBus } from '@unidev-hub/mfe-toolkit/communication';

// Create a new event bus
const eventBus = new EventBus();

// Add a listener
const unsubscribe = eventBus.on('user:login', (event) => {
  console.log('User logged in:', event.payload);
});

// Emit an event
eventBus.emit('user:login', { id: 123, name: 'John' }, 'auth-mfe');

// Clean up
unsubscribe();

SharedState

Manages shared state between MFEs:

import { SharedState } from '@unidev-hub/mfe-toolkit/communication';
import { EventBus } from '@unidev-hub/mfe-toolkit/communication';

// Create a new shared state manager
const eventBus = new EventBus();
const sharedState = new SharedState(eventBus);

// Set a value
sharedState.set('user', 'preferences', { theme: 'dark', fontSize: 'medium' });

// Get a value
const preferences = sharedState.get('user', 'preferences');

// Update a value
sharedState.update('user', 'preferences', (prev) => ({
  ...prev,
  theme: 'light'
}));

// Clear values
sharedState.clearNamespace('user');

// Get a snapshot of all state
const snapshot = sharedState.getSnapshot();

🛠️ Utils

MFE Loader

Utilities for loading MFE modules:

import { loadMfeModule, preloadMfeModule } from '@unidev-hub/mfe-toolkit/utils';

// Load a module from an MFE
loadMfeModule('products', 'ProductsApp')
        .then(ProductsApp => {
          // Use the loaded module
          console.log('Products app loaded');
        })
        .catch(err => {
          console.error('Failed to load Products app:', err);
        });

// Preload a module for faster access later
preloadMfeModule('vendors', 'VendorsApp');

MFE Registry

Utilities for managing MFE configurations:

import { mfeRegistry, initMfeRegistry } from '@unidev-hub/mfe-toolkit/utils';

// Initialize the registry
initMfeRegistry({
  products: {
    name: 'products',
    scope: 'products',
    module: 'ProductsApp',
    remoteEntry: 'https://products.example.com/remoteEntry.js'
  },
  vendors: {
    name: 'vendors',
    scope: 'vendors',
    module: 'VendorsApp'
  }
}, true); // true to load remote entries automatically

// Register a new MFE
mfeRegistry.register({
  name: 'orders',
  scope: 'orders',
  module: 'OrdersApp'
});

// Get an MFE configuration
const productsConfig = mfeRegistry.getConfig('products');

🔍 Examples

Basic MFE Shell

A simple shell application that loads MFEs:

import React from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { MantineProvider } from '@mantine/core';
import { MfeCommunicationProvider, MfeContainer } from '@unidev-hub/mfe-toolkit';

function App() {
  return (
          <MantineProvider>
            <BrowserRouter>
              <MfeCommunicationProvider
                      shellName="e-commerce-shell"
                      shellVersion="1.0.0"
                      initialRegistry={{
                        products: {
                          name: 'products',
                          scope: 'products',
                          module: 'ProductsApp'
                        },
                        cart: {
                          name: 'cart',
                          scope: 'cart',
                          module: 'CartApp'
                        }
                      }}
              >
                <div className="app-shell">
                  <header>
                    <h1>E-Commerce Platform</h1>
                    <nav>
                      <a href="/">Home</a>
                      <a href="/products">Products</a>
                      <a href="/cart">Cart</a>
                    </nav>
                  </header>

                  <main>
                    <Routes>
                      <Route path="/" element={<HomePage />} />
                      <Route
                              path="/products/*"
                              element={<MfeContainer name="products" module="ProductsApp" />}
                      />
                      <Route
                              path="/cart/*"
                              element={<MfeContainer name="cart" module="CartApp" />}
                      />
                    </Routes>
                  </main>
                </div>
              </MfeCommunicationProvider>
            </BrowserRouter>
          </MantineProvider>
  );
}

Cross-MFE Data Sharing

Example of how to share data between MFEs:

// In Products MFE
import React from 'react';
import { useMfeEvents, useMfeState } from '@unidev-hub/mfe-toolkit';

function ProductList() {
  const [products, setProducts] = useState([]);
  const { emit } = useMfeEvents('products');
  const [cartCount, setCartCount] = useMfeState('cart', 'itemCount', 0);

  const addToCart = (product) => {
    emit('cart:add-item', product);
    setCartCount(prev => prev + 1);
  };

  return (
          <div>
            <h2>Products</h2>
            <p>Cart Items: {cartCount}</p>

            {products.map(product => (
                    <div key={product.id}>
                      <h3>{product.name}</h3>
                      <button onClick={() => addToCart(product)}>
                        Add to Cart
                      </button>
                    </div>
            ))}
          </div>
  );
}

// In Cart MFE
import React, { useEffect } from 'react';
import { useMfeEvents, useMfeState } from '@unidev-hub/mfe-toolkit';

function Cart() {
  const [items, setItems] = useState([]);
  const [itemCount, setItemCount] = useMfeState('cart', 'itemCount', 0);
  const { on } = useMfeEvents('cart');

  useEffect(() => {
    const unsubscribe = on('cart:add-item', (product) => {
      setItems(prev => [...prev, product]);
      setItemCount(items.length + 1);
    });

    return unsubscribe;
  }, [on, items.length]);

  return (
          <div>
            <h2>Cart ({itemCount} items)</h2>

            {items.map(item => (
                    <div key={item.id}>
                      <h3>{item.name}</h3>
                      <p>${item.price}</p>
                    </div>
            ))}
          </div>
  );
}

🌐 Advanced Topics

Authentication Across MFEs

Managing authentication across MFEs:

// In Auth MFE
import { useMfeState, useMfeEvents } from '@unidev-hub/mfe-toolkit';

function AuthManager() {
  const [user, setUser] = useMfeState('auth', 'currentUser', null);
  const { emit } = useMfeEvents('auth');
  
  const login = async (credentials) => {
    const userData = await api.login(credentials);
    setUser(userData);
    emit('auth:login', userData);
  };
  
  const logout = async () => {
    await api.logout();
    setUser(null);
    emit('auth:logout');
  };
  
  // Rest of the component
}

// In any other MFE
function ProtectedFeature() {
  const [user] = useMfeState('auth', 'currentUser', null);
  const { on } = useMfeEvents('app');
  
  useEffect(() => {
    const loginHandler = on('auth:login', (userData) => {
      console.log('User logged in:', userData);
    });
    
    const logoutHandler = on('auth:logout', () => {
      // Redirect to login page
    });
    
    return () => {
      loginHandler();
      logoutHandler();
    };
  }, [on]);
  
  if (!user) {
    return <div>Please log in to access this feature</div>;
  }
  
  return <div>Protected content</div>;
}

MFE Routing Coordination

Coordinating routing across MFEs:

// In the Shell App
import { MfeCommunicationProvider, useMfeEvents } from '@unidev-hub/mfe-toolkit';

function AppShell() {
  const { emit } = useMfeEvents('shell');
  
  // Broadcast route changes
  useEffect(() => {
    const handleRouteChange = () => {
      emit('router:change', {
        pathname: window.location.pathname,
        search: window.location.search,
        hash: window.location.hash
      });
    };
    
    window.addEventListener('popstate', handleRouteChange);
    
    // Custom event for programmatic navigation
    const originalPushState = window.history.pushState;
    window.history.pushState = function() {
      originalPushState.apply(this, arguments);
      handleRouteChange();
    };
    
    return () => {
      window.removeEventListener('popstate', handleRouteChange);
      window.history.pushState = originalPushState;
    };
  }, [emit]);
  
  // Rest of the shell app
}

// In an MFE
function MfeComponent() {
  const { on, emit } = useMfeEvents('mfe-name');
  const navigate = useNavigate();
  
  // Listen for route changes from the shell
  useEffect(() => {
    const unsubscribe = on('router:change', (routeData) => {
      // Handle route changes from other MFEs
      // ...
    });
    
    return unsubscribe;
  }, [on]);
  
  // Notify shell about navigation
  const navigateTo = (path) => {
    emit('router:navigate', { path });
    navigate(path);
  };
  
  return (
    <div>
      <button onClick={() => navigateTo('/some-path')}>Navigate</button>
    </div>
  );
}

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


Built with ❤️ by the Unidev Hub team.