侧边栏壁纸
  • 累计撰写 54 篇文章
  • 累计创建 4 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

工程化:模块联邦

模块联邦(Module Federation)是 Webpack 5 引入的一项革命性功能,它允许在独立的 JavaScript 应用程序之间动态共享代码模块,从而实现微前端架构和跨应用代码复用。核心思想是"一个应用可以消费另一个应用暴露的模块"。

远程应用 Webpack 配置暴露出口

const { ModuleFederationPlugin } = require('webpack').container;
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: './src/index.js', // 主入口,我们简化一下,可以直接是bootstrap.js
  devServer: {
    port: 3001, // 远程应用运行在3001端口
    hot: true,
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-react'],
          },
        },
      },
    ],
  },
  plugins: [
    // 模块联邦插件
    new ModuleFederationPlugin({
      name: 'app_components', // 唯一名称,供其他应用引用
      filename: 'remoteEntry.js', // 入口清单文件名,固定
      exposes: { // 暴露的模块列表
        './Button': './src/components/Button', // 别名: 模块路径
        './Header': './src/components/Header',
      },
      shared: { // 共享的库
        react: { singleton: true, requiredVersion: '^18.0.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};

主机应用使用

import React from 'react';
import ReactDOM from 'react-dom/client';
import LocalComponent from './LocalComponent'; // 本地的一个组件

// 1. 动态导入远程模块
const RemoteButton = React.lazy(() => import('app_components/Button'));
const RemoteHeader = React.lazy(() => import('app_components/Header'));

const App = () => {
  return (
    <div style={{ padding: '20px', border: '2px solid #ccc', margin: '20px' }}>
      <h2>主应用 (运行在 localhost:3000)</h2>
      <LocalComponent />
      <hr />
      {/* 2. 使用Suspense加载远程组件 */}
      <React.Suspense fallback={<div>正在加载远程组件...</div>}>
        <RemoteHeader title="我是远程的标题" />
        <RemoteButton onClick={() => alert('按钮来自远程应用!')}>
          点我
        </RemoteButton>
      </React.Suspense>
    </div>
  );
};

const root = ReactDOM.createDocument.getElementById('root');
root.render(<App />);

Webpack 配置引入入口

const { ModuleFederationPlugin } = require('webpack').container;
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  devServer: {
    port: 3000, // 主机应用运行在3000端口
    hot: true,
  },
  module: { /* ... 类似远程的babel规则 ... */ },
  plugins: [
    new ModuleFederationPlugin({
      name: 'main_app',
      remotes: { // 定义远程应用
        // 格式: “远程应用在联邦中的名称”@“远程应用的入口文件地址”
        app_components: 'app_components@http://localhost:3001/remoteEntry.js',
      },
      shared: { // 共享的库,必须和远程应用协调一致
        react: { singleton: true, requiredVersion: '^18.0.0' },
        'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
    }),
  ],
};
0

评论区