Webpack 5 Module Federation 是什么?如何使用?

Module Federation

模块联邦允许多个独立构建的应用在运行时共享模块,是微前端的实现方案之一。

核心概念

概念 说明
Host 消费远程模块的应用(主应用)
Remote 暴露模块的应用(子应用)
Shared 共享依赖(如 react、vue)

Remote 配置(子应用)

// webpack.config.js (remote app)
const { ModuleFederationPlugin } = require('webpack').container

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'remoteApp',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/components/Button',
        './utils': './src/utils'
      },
      shared: {
        react: { singleton: true },
        'react-dom': { singleton: true }
      }
    })
  ]
}

Host 配置(主应用)

// webpack.config.js (host app)
new ModuleFederationPlugin({
  name: 'hostApp',
  remotes: {
    remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js'
  },
  shared: {
    react: { singleton: true },
    'react-dom': { singleton: true }
  }
})

使用远程模块

// 同步加载
import Button from 'remoteApp/Button'
function App() {
  return <Button>Click</Button>
}

// 异步加载(推荐)
const RemoteButton = React.lazy(() => import('remoteApp/Button'))
function App() {
  return (
    <Suspense fallback="Loading">
      <RemoteButton>Click</RemoteButton>
    </Suspense>
  )
}

shared 详解

shared: {
  react: {
    singleton: true,      // 只加载一个实例
    requiredVersion: '^18',
    eager: false,          // 是否同步加载
  }
}
// 如果 host 和 remote 都依赖 react,运行时只加载一个版本

运行时加载 remote

// 动态加载远程模块
async function loadRemote(name, module) {
  // 初始化容器
  await __webpack_init_sharing__('default')
  const container = await loadRemoteContainer(name)
  await container.init(__webpack_share_scopes__.default)
  const factory = await container.get(module)
  return factory()
}

const Button = await loadRemote('remoteApp', './Button')

Module Federation 的优势

  1. 运行时集成:不需要构建时知道子应用
  2. 依赖共享:react 等公共依赖只加载一次
  3. 独立部署:子应用独立构建部署
  4. 按需加载:远程模块按需 import

vs qiankun

特性 Module Federation qiankun
共享依赖 ✅ 自动共享 ❌ 各自加载
集成粒度 组件级 应用级
JS 沙箱 ❌ ✅
CSS 隔离 ❌ ✅
技术栈 需统一(shared) 可不同

Vite 中的 Module Federation

// 使用 vite-plugin-federation
import federation from '@originjs/vite-plugin-federation'

export default {
  plugins: [
    federation({
      name: 'host',
      remotes: {
        remote: 'http://localhost:3001/assets/remoteEntry.js'
      },
      shared: ['vue']
    })
  ]
}

适用场景

注意事项

  1. 共享依赖的版本要兼容
  2. 没有原生 JS/CSS 隔离
  3. 调试时需要注意远程模块的 source map

同分类其他题目