1. 概述

微前端是一种软件架构,可以将前端应用拆分成一些更小的能够独立开发部署的微型应用,然后再将这些微应用进行组合使其成为整体应用的架构模式。

微前端架构类似于组件架构,不同的是组件不能独立构建和发布,微前端中的应用是可以的,微前端架构与框架无关,每个微应用都可以使用不同的框架,也可以不使用框架。

众所周知项目如果想从一个框架迁移到另个一个框架是很耗费时间和精力的,使用微前端架构就可以解决这个问题,在保留原有项目的同时可以完全使用新的框架开发新的需求,然后再使用微前端将旧的项目和新的项目进行整合,这样既可以使产品得到更好的体验,也可以使团队成员在技术上得到进步,产品开发成本也降到最低。

而且微前端中的每个部分都可以独立部署,这样就避免了一处修改全部发布的复杂工作。

在微前端中每个参与团队都可以根据自身的擅长面使用技术栈,不需要统一技术栈开发。

微前端在实现上存在四个问题。

  1. 除了存在多个微应用以外,还存在一个容器应用,每个微应用都需要被注册到容器应用中,微前端中的每个应用在浏览器中都是一个独立的js模块,通过模块化的方式被容器应用启动和运行。使用模块化的方式运行应用可以防止不同的微应用在同时运行时发生冲突。

  2. 当路由发生变化时,容器应用首先会拦截路由的变化,根据路由匹配微前端应用,匹配之后再启动微应用路由,匹配具体的页面。

  3. 微应用中通过发布订阅模式实现状态共享,比如使用RxJS

  4. 通过import-map和webpack中的externals属性实现依赖库之间的共享。

在微前端架构中,微应用被打包为模块,但浏览器并不支持模块化,需要使用systemjs来实现浏览器中的模块化。

systemjs是一个用于实现模块化的js库,有属于自己的模块化规范,在开发阶段我们可以使用ES模块规范,然后使用webpack将其转换为systemjs支持的模块。

首先需要在webpack配置的输出位置,指定打包使用system模块。

output: {
    ...
    libraryTarget: "system"
}

还要使用externals将公共模块排除。

externals: ['react', 'react-dom', 'react-router-dom']

还有就是不能通过webpack将打包后的js注入到页面中,应该使用system加载进来。

<script src="...system.js"></script>
<script>
    {
        "imports": {
            "react": ".../react.js",
            "react-dom": ".../react-dom.js",
            "react-router-dom": ".../react-router-dom.js"
        }
    }
</script>
<script>
    System.import("./index.js")
</script>

这就是system.js的一个基本使用。

2. Single-Spa

single-spa是一个实现微前端的框架,在single-spa框架中有三种类型的微前端应用。

single-spa-application是微前端架构中的微应用,这种微应用可以基数vuereactangular等框架开发,这种微应用是和路由相关联的,比如访问某一个path的时候要访问哪一个微应用。和他相关联的是single-spa-parcel他的使用方式和application类似不同点是不和路由进行关联,主要用于跨应用共享UI组件。

single-spa root config这种类型的微应用是微前端架构中的容器微应用,通过容器应用加载和管理普通的微应用。

utility modules是公共模块,不是渲染UI组件的,用于跨应用共享js逻辑。

这三种都是单独的应用,都可以单独开发,构建和发布。

创建一个微应用

npm install create-single-spa -g

mkdir workspace

cd workspace

create-single-spa

npm run start

root-config.js是容器应用的入口文件。

import { registerApplication, start } from 'single-spa'
// 注册微应用
registerApplication({
    name: "@singgle-spa/welcome", // 开发者名称
    app: () => System.import(""), // 模块打包完成的地址
    activeWhen: ['/'] // 加载时机
})
// 启动微应用
start({
    urlRerouteOnly: true
})

3. Module Federation

模块联邦是webpack5中新增的一项功能,可以实现跨应用共享模块。

导出对象

// 首先需要在webpack配置文件中导入模块联邦插件。
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
// 
new ModuleFederationPlugin({
    // 模块文件名称,其他应用引入当前模块时需要加载的文件名字
    filename: 'aaa.js',
    // 模块名称,具有为一性
    name: 'aaa',
    // 当前模块具体导出的内容
    exposes: {
        './aaa': './src/index'
    }
})

导入对象

// 首先需要在webpack配置文件中导入模块联邦插件。
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')

new ModuleFederationPlugin({
    name: 'bbb',
    // 配置导入的映射
    remotes: {
        bbb: 'aaa@address_path'
    }
})

加载

// 因为是异步导入模块,所以要使用import异步加载
import('bbb/aaa').then(content => {console.log(content)})

// import('bootstrap.js')
// bootstrap.js
// import 'bbb/aaa'

转载须知

如转载必须标明文章出处文章名称文章作者,格式如下:

转自:【致前端 - https://madaozhijian.com】 微前端概述  "隐冬"