返回

Module Federation:React与Angular的跨应用共存

前端

使用 Module Federation 在 React 和 Angular 中构建微服务

Module Federation 简介

随着现代 Web 应用变得愈发复杂,单体应用的弊端日益显现。为了应对这一挑战,微服务架构应运而生,它将应用分解为多个独立的小应用,以便于管理和维护。Module Federation 是一种实现微服务架构的有效方法,它允许在不同的应用程序之间共享模块。

Module Federation 的落地实践

Module Federation 适用于 React 和 Angular 等主流 JavaScript 框架。在 React 中,可以使用 create-react-app 创建项目,并利用 webpack-module-federation 插件配置 Module Federation。而在 Angular 中,则可以使用 @angular-architects/module-federation 库进行配置。

模块配置

React + Vite 项目:

// webpack.config.js
const ModuleFederationPlugin = require('webpack').ModuleFederationPlugin;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: 'react-app',
      filename: 'remoteEntry.js',
      exposes: {
        './Counter': './src/components/Counter.jsx',
      },
      shared: {
        react: {
          singleton: true,
          requiredVersion: '^18.0.0',
        },
        'react-dom': {
          singleton: true,
          requiredVersion: '^18.0.0',
        },
      },
    }),
  ],
};

Angular 项目:

// angular.json
{
  "projects": {
    "angular-app": {
      "architect": {
        "build": {
          "options": {
            "outputPath": "dist/angular-app",
            "moduleFederation": true,
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico"
            ],
            "scripts": [],
            "styles": [],
            "vendorChunk": false,
            "extractCss": true,
            "sourceMap": true,
            "optimization": true,
            "namedChunks": false,
            "aot": true,
            "webpackConfig": "webpack.config.js"
          },
          "configuration": {
            "remoteOnly": true
          }
        }
      }
    }
  }
}

模块共享

配置好 Module Federation 后,便可实现不同应用程序之间的模块共享。

React 项目:

// App.jsx
import React, { useEffect, useState } from 'react';

const App = () => {
  const [count, setCount] = useState(0);

  useEffect(() => {
    import('./Counter').then(({ Counter }) => {
      setCount(Counter.increment(count));
    });
  }, []);

  return <h1>Count: {count}</h1>;
};

export default App;

Angular 项目:

// app.component.ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  count: number = 0;

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http
      .get<number>('http://localhost:3000/remoteEntry.js')
      .subscribe((count) => {
        this.count = count;
      });
  }
}

常见问题

  • 模块名称冲突: 避免不同应用程序使用相同的模块名称。
  • 模块版本冲突: 确保不同应用程序使用同一模块的相同版本。
  • 模块加载失败: 检查远程模块是否可访问,并确保网络连接正常。

总结

Module Federation 为构建分布式微服务提供了有效方法,实现了不同应用程序之间的模块共享和代码重用。通过遵循本文中的步骤,开发者可以轻松地在 React 和 Angular 中落地 Module Federation,从而优化开发效率和应用程序性能。