React&微前端&模块联盟概念讲解

React&微前端&模块联盟概念讲解@react,webpack,微前端

什么是微前端?

微前端架构(micro frontends architecture)设计风格为应用程序的前端所做的,就像微服务为后端所做的那样,将整体结构分解成更小的组件,然后可以在单个页面上组装。

微前端的优缺点

优点:

  • 微前端更加模块化和可重用。
  • 微前端更具可扩展性。
  • 微前端更易于维护。
  • 独立和更快地开发。
  • 测试单独的应用程序很容易。
  • 不同的前端技术可用于不同的项目(如 React、Angular、Vue.js 等)。
    缺点:
  • 测试整个应用程序并不容易。
  • 共享代码、状态(数据)等并不容易。

模块联盟Module Federation | webpack

模块联盟允许一个JavaScript应用程序动态地从另一个应用程序加载代码,并在此过程中共享依赖关系。如果一个使用联盟模块的应用程序没有联盟代码所需的依赖,Webpack将从该联盟的构建源头下载缺少的依赖。
前提是确保你已经安装了最新的Node.js。对React.js和Webpack 5+有基本了解。

示例

我将在本文中创建2个应用程序。第一个:容器应用,将被用作微前端的基础。第二:计数器应用,将在容器应用内被渲染。
让我们从设置环境开始,我使用create-mf-app来创建一个react应用。

安装Container app

在终端上运行以下npx命令,使用 "create-mf-app "安装和引导应用程序。

npx create-mf-app

React&微前端&模块联盟概念讲解_第1张图片
完成第一步后,初始化后的目录是这样的
React&微前端&模块联盟概念讲解_第2张图片我不会深入讲解这个目录结构,因为它和create-react-app目录结构一样。

值得注意的是,这里的index.js文件是动态导入了一个App.js

import('./App')

接下来让我们快速开始初始化另一个叫做Counter的app,与创造Container app一样

npx create-mf-app

React&微前端&模块联盟概念讲解_第3张图片

在这里,我在component目录下创建了一个Counter组件
src/components/Counter.jsx

import React, { useState } from "react";
export const Counter = () => {
    const [count, setCount] = useState(0);
    const onIncrement = () => setCount(count + 1);
    const onDecrement = () => setCount(count - 1);
    return (
      <div>
        <h1>Counter App</h1>
        <p>Current count: <strong>{count}</strong></p>
        <button onClick={onIncrement}>+</button>
        <button onClick={onDecrement}>-</button>
      </div>
    );
}

让我们在Counter app里更新webpack.config.js文件,在plugins的数组里加入ModuleFederationPlugin插件。

webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;
module.exports = {
  output: {
    publicPath: "http://localhost:8081/",
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },
  devServer: {
    port: 8081,
    historyApiFallback: true,
  },
  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },
  plugins: [ // This is important part
    new ModuleFederationPlugin({
      name: "counter",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        "./Counter": "./src/components/Counter",
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
};

让我们来理解一下这个插件的配置项:
name:远程app的名称
filename:Counter app的入口点 (remoteEntry.js)。
remotes:在此处添加 remotes 项(与容器相关),必须定义从远程应用程序公开的所有入口点,远程入口结构为:{ “app-name”: “name@/remoteEntry.js” }
exposes:您要向容器应用程序公开的所有组件名称。
shared:容器所有要在容器和计数器应用程序之间共享的依赖项。

src/App.jsx

import React from "react";
import ReactDOM from "react-dom";
import { Counter } from 'counter/Counter';
import "./index.css";
const App = () => (
  <div className="container">
    <h1>Container App</h1>
    <Counter /> // Micro frontend app
  </div>
);
ReactDOM.render(<App />, document.getElementById("app"));


然后运行这两个app
React&微前端&模块联盟概念讲解_第4张图片
感谢阅读!!

你可能感兴趣的:(react学习分享,web前端进阶,前端,react.js,javascript)