微前端架构

微前端

微前端是一种软件架构,类似于组件级应用,微前端可应用于项目技术栈的更新,独立发布,每个微应用都可以使用不同的框架

实现微前端

1.多个微应用之间的组合:微应用被注册在容器应用中
2.微应用中实现路由:微前端架构中,路由发生变化时,容器应用根据路由匹配微前端应用,匹配到微前端应用之后再启动微应用路由匹配具体的页面组件
3.微应用之间的状态共享,通过发布订阅模式,例如使用RxJS
4.微应用之间实现框架和库的共享:通过import-map(请求网络包)和webpack中的externals属性(哪些包不用被打包在应用中)

systemjs

webpack打包是将打包出的js文件通过script标签进入到public下index.html文件中。而使用systemjs时,webpack打包不将打包后的js文件通过script引入而是在index.html文件中加载如下代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>systemjs-react</title>
    <script type="systemjs-importmap">
      {
        "imports": {
          "react": "https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js",
          "react-dom": "https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js",
          "react-router-dom": "https://cdn.jsdelivr.net/npm/react-router-dom@5.2.0/umd/react-router-dom.min.js"
        }
      }
    </script>
    <script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.0/dist/system.min.js"></script>
  </head>
  <body>
    <div id="root"></div>
    <script>
      System.import("./index.js")//通过引入system.js就可以有System对象
    </script>
  </body>
</html>

webpack打包使用systemjs必用代码
在output中libraryTarget: "system"

  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      inject: false//将打包出的js模块不直接引入
    })
  ],
  externals: ["react", "react-dom", "react-router-dom"]

模块联邦微应用

faker包用于生成模拟数据
模块联邦教程
添加两个模块,一个产品模块,一个容器模块,使用ModuleFederationPlugin插件,将产品模块导入到容器模块中,运行容器模块即可查看产品模块
产品模块引用faker,购物车模块引用faker,启动容器模块时会被引用两次,所以应该实现模块共享,在product和cart模块中的shared数组字段中添加faker,若两模块使用版本冲突,应配置faker版本为较高的模块
在容器应用导入微应用后,应该有权限决定微应用的挂载位置,所以,微应用应该导出挂载方法mount,参数为微应用挂载的DOM元素,在mount方法中获取到DOM元素,定义DOM元素的innerHTML方法用于显示,这样微应用就运行不起来,需要判断环境来执行mount方法

案例基于模块联邦的微前端实现方案

案例教程
有marketing(通过Material-UI和React)、auth、dashboard,container(React)三个模块
容器应用使用BrowserHistory路由,微应用使用MemoryHistory路由,只允许容器应用更新url,微应用路由发生变化时不体现在url上而是向容器应用传递路由方法在mount中history.listen方法对路由进行监听
容器应用发生变化时只会匹配微应用,微应用路由并不会响应容器路由的变化,所以要想解决这一问题微应用需向容器应用返回方法,监听容器应用路由变化调用该方法通知微应用更新路由
微应用因为使用内存路由跳转时url无法显示,而启动微应用自己的项目时应该显示解决办法

懒加载微应用

react中的lazy方法和Suspense组件

设置登录状态

每个微应用都会用到登录状态以及设置登录状态的方法,所以登录状态和设置登录状态的方法放置在容器应用中,传递通过prpos传值方式给微应用的mount方法

dashboard vue微应用

webpack.config.js对于vue项目的配置

const HtmlWebpackPlugin = require("html-webpack-plugin")
const { VueLoaderPlugin } = require("vue-loader")
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin")
const packageJson = require("./package.json")

module.exports = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    publicPath: "http://localhost:8083/",
    filename: "[name].[contentHash].js"
  },
  resolve: {
    extensions: [".js", ".vue"]
  },
  devServer: {
    port: 8083,
    historyApiFallback: true,
    headers: {
      "Access-Control-Allow-Origin": "*"
    }
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|woff|svg|eot|ttf)$/i,
        use: [
          {
            loader: "file-loader"
          }
        ]
      },
      {
        test: /\.vue$/,
        use: "vue-loader"
      },
      {
        test: /\.scss|\.css$/,
        use: ["vue-style-loader", "style-loader", "css-loader", "sass-loader"]
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"],
            plugins: ["@babel/plugin-transform-runtime"]
          }
        }
      }
    ]
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "dashboard",
      filename: "remoteEntry.js",
      exposes: {
        "./DashboardApp": "./src/bootstrap"
      },
      shared: packageJson.dependencies
    }),
    new HtmlWebpackPlugin({
      template: "./public/index.html"
    }),
    new VueLoaderPlugin()
  ]
}

dashboardApp路由保护

posted @ 2024-05-14 17:27  穹顶之下影  阅读(6)  评论(0编辑  收藏  举报