一、微前端简介

微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用可以独立运行、独立开发、独立部署。

微前端的好处

  • 应用自治。只需要遵循统一的接口规范或者框架,以便于系统集成到一起,相互之间是不存在依赖关系的。
  • 单一职责。每个前端应用可以只关注于自己所需要完成的功能。
  • 技术栈无关。你可以使用 Angular 的同时,又可以使用 React 和 Vue。

微前端的缺点

  • 应用的拆分基础依赖于基础设施的构建,一旦大量应用依赖于同一基础设施,那么维护变成了一个挑战。
  • 拆分的粒度越小,便意味着架构变得复杂、维护成本变高。
  • 技术栈一旦多样化,便意味着技术栈混乱

微前端由哪些模块组成

当下微前端主要采用的是组合式应用路由方案,该方案的核心是“主从”思想,即包括一个基座(MainApp)应用若干个微(MicroApp)应用,基座应用大多数是一个前端SPA项目,主要负责应用注册,路由映射,消息下发等,而微应用是独立前端项目,这些项目不限于采用React,Vue,Angular或者JQuery开发,每个微应用注册到基座应用中,由基座进行管理,但是如果脱离基座也是可以单独访问,基本的流程如下图所示

是否要用微前端

微前端最佳的使用场景是一些B端的管理系统,既能兼容集成历史系统,也可以将新的系统集成进来,并且不影响原先的交互体验

二、微前端实战

微前端现有的落地方案可以分为三类,自组织模式、基座模式以及模块加载模式

2.1 SingleSpa实战

官网 https://zh-hans.single-spa.js.org/docs/configuration

适用场景:项目庞大,多个子项目整合在一个大的项目中。即使子项目的所用的技术栈不同,比如vue,react, angular有相应的single-spa的轮子,可以进行整合

1.构建子应用

首先创建一个vue子应用,并通过single-spa-vue来导出必要的生命周

vue create spa-vue
npm install single-spa-vue
// main.jsimport singleSpaVue from 'single-spa-vue';const appOptions = {el: '#vue',router,render: h => h(App)
}// 在非子应用中正常挂载应用
if(!window.singleSpaNavigate){delete appOptions.el;new Vue(appOptions).$mount('#app');
}const vueLifeCycle = singleSpaVue({Vue,appOptions
});// 子应用必须导出以下生命周期:bootstrap、mount、unmount
export const bootstrap = vueLifeCycle.bootstrap;
export const mount = vueLifeCycle.mount;
export const unmount = vueLifeCycle.unmount;
export default vueLifeCycle;
// router.js// 配置子路由基础路径
const router = new VueRouter({mode: 'history',base: '/vue',   //改变路径配置routes
})

2. 将子模块打包成类库

//vue.config.js
module.exports = {configureWebpack: {// 把属性挂载到window上方便父应用调用 window.singleVue.bootstrap/mount/unmountoutput: {library: 'singleVue',libraryTarget: 'umd'},devServer:{port:10000}}
}

3. 主应用搭建

<div id="nav"><router-link to="/vue">vue项目<router-link> <!--将子应用挂载到id="vue"标签中--><div id="vue">div>
div>
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import {registerApplication,start} from 'single-spa'Vue.config.productionTip = falseasync function loadScript(url) {return new Promise((resolve,reject)=>{let script = document.createElement('script')script.src = url script.onload = resolvescript.onerror = rejectdocument.head.appendChild(script)})
}// 注册应用
registerApplication('myVueApp',async ()=>{console.info('load')// singlespa问题 // 加载文件需要自己构建script标签 但是不知道应用有多少个文件// 样式不隔离// 全局对象没有js沙箱的机制 比如加载不同的应用 每个应用都用同一个环境// 先加载公共的await loadScript('http://localhost:10000/js/chunk-vendors.js')await loadScript('http://localhost:10000/js/app.js')return window.singleVue // bootstrap mount unmount},// 用户切换到/vue下 我们需要加载刚才定义的子应用location=>location.pathname.startsWith('/vue'),
)start()new Vue({router,render: h => h(App)
}).$mount('#app')

4. 动态设置子应用publicPath

if(window.singleSpaNavigate){__webpack_public_path__ = 'http://localhost:10000/'
}

2.2 qiankun实战

文档 https://qiankun.umijs.org/zh/guide

  • qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
  • qiankun 孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台,在经过一批线上应用的充分检验及打磨后,我们将其微前端内核抽取出来并开源,希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统,同时也希望通过社区的帮助将 qiankun 打磨的更加成熟完善。
  • 目前 qiankun 已在蚂蚁内部服务了超过 200+ 线上应用,在易用性及完备性上,绝对是值得信赖的。

1. 主应用搭建

<template><!--注意这里不要写app 否则跟子应用的加载冲突<div id="app">--><div><el-menu :router="true" mode="horizontal"><!-- 基座中可以放自己的路由 --><el-menu-item index="/">Home</el-menu-item><!-- 引用其他子应用 --><el-menu-item index="/vue">vue应用</el-menu-item><el-menu-item index="/react">react应用</el-menu-item></el-menu><router-view /><!-- 其他子应用的挂载节点 --><div id="vue" /><div id="react" /></div>
</template>

2. 注册子应用


import { registerMicroApps,start } from 'qiankun'
// 基座写法
const apps = [{name: 'vueApp', // 名字// 默认会加载这个HTML,解析里面的js动态执行 (子应用必须支持跨域)entry: '//localhost:10000',  container: '#vue', // 容器activeRule: '/vue', // 激活的路径 访问/vue把应用挂载到#vue上props: { // 传递属性给子应用接收a: 1,}},{name: 'reactApp',// 默认会加载这个HTML,解析里面的js动态执行 (子应用必须支持跨域)entry: '//localhost:20000',  container: '#react',activeRule: '/react' // 访问/react把应用挂载到#react上},
]// 注册
registerMicroApps(apps)
// 开启
start({prefetch: false // 取消预加载
})

3. 子Vue应用

// src/router.jsconst router = new VueRouter({mode: 'history',// base里主应用里面注册的保持一致base: '/vue',routes
})

不要忘记子应用的钩子导出。

// main.jsimport Vue from 'vue'
import App from './App.vue'
import router from './router'Vue.config.productionTip = falselet instance = null
function render() {instance = new Vue({router,render: h => h(App)}).$mount('#app') // 这里是挂载到自己的HTML中 基座会拿到挂载后的HTML 将其插入进去
}// 独立运行微应用
// https://qiankun.umijs.org/zh/faq#%E5%A6%82%E4%BD%95%E7%8B%AC%E7%AB%8B%E8%BF%90%E8%A1%8C%E5%BE%AE%E5%BA%94%E7%94%A8%EF%BC%9F
if(!window.__POWERED_BY_QIANKUN__) {render()
}// 如果被qiankun使用 会动态注入路径
if(window.__POWERED_BY_QIANKUN__) {// qiankun 将会在微应用 bootstrap 之前注入一个运行时的 publicPath 变量,你需要做的是在微应用的 entry js 的顶部添加如下代码:__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}// 子应用的协议 导出供父应用调用 必须导出promise
export async function bootstrap(props) {} // 启动可以不用写 需要导出方法
export async function mount(props) {render()
}
export async function unmount(props) {instance.$destroy()
}

4. 配置vue.config.js

// vue.config.jsmodule.exports = {devServer:{port:10000,headers:{'Access-Control-Allow-Origin':'*' //允许访问跨域}},configureWebpack:{// 打umd包output:{library:'vueApp',libraryTarget:'umd'}}
}

5.子React应用

使用react作为子应用

// app.jsimport logo from './logo.svg';
import './App.css';
import {BrowserRouter,Route,Link} from 'react-router-dom'function App() {return (// /react跟主应用配置保持一致<BrowserRouter basename="/react"><Link to="/">首页</Link><Link to="/about">关于</Link><Route path="/" exact render={()=>(<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a></header></div>)} /><Route path="/about" exact render={()=>(<h1>About Page</h1>)}></Route></BrowserRouter>);
}export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';function render() {ReactDOM.render(<React.StrictMode><App /></React.StrictMode>,document.getElementById('root'));
}// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();// 独立运行
if(!window.__POWERED_BY_QIANKUN__){render()
}// 子应用协议
export async function bootstrap() {}
export async function mount() {render()
}
export async function unmount() {ReactDOM.unmountComponentAtNode(document.getElementById("root"));
}

重写react中的webpack配置文件 (config-overrides.js)

yarn add react-app-rewired --save-dev

修改package.json文件

// react-scripts 改成 react-app-rewired
"scripts": {"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test","eject": "react-app-rewired eject"},

在根目录新建配置文件

// 配置文件重写
touch config-overrides.js
// config-overrides.jsmodule.exports = {webpack: (config) => {// 名字和基座配置的一样config.output.library = 'reactApp';config.output.libraryTarget = "umd";config.output.publicPath = 'http://localhost:20000/'return config},devServer: function (configFunction) {return function (proxy, allowedHost) {const config = configFunction(proxy, allowedHost);// 配置跨域config.headers = {"Access-Control-Allow-Origin": "*",};return config;};},
};

配置.env文件

根目录新建.env

PORT=30000
# socket发送端口
WDS_SOCKET_PORT=30000

路由配置

import { BrowserRouter, Route, Link } from "react-router-dom"const BASE_NAME = window.__POWERED_BY_QIANKUN__ ? "/react" : "";function App() {return (<BrowserRouter basename={BASE_NAME}><Link to="/">首页Link><Link to="/about">关于Link><Route path="/" exact render={() => <h1>hello homeh1>}>Route><Route path="/about" render={() => <h1>hello abouth1>}>Route>BrowserRouter>);
}

2.3 飞冰微前端实战

官方接入指南 https://micro-frontends.ice.work/docs/guide

  • icestark 是一个面向大型系统的微前端解决方案,适用于以下业务场景:
  • 后台比较分散,体验差别大,因为要频繁跳转导致操作效率低,希望能统一收口的一个系统内
  • 单页面应用非常庞大,多人协作成本高,开发/构建时间长,依赖升级回归成本高
  • 系统有二方/三方接入的需求

icestark 在保证一个系统的操作体验基础上,实现各个微应用的独立开发和发版,主应用通过 icestark 管理微应用的注册和渲染,将整个系统彻底解耦。

1. react主应用编写

$ npm init ice icestark-layout @icedesign/stark-layout-scaffold
$ cd icestark-layout
$ npm install
$ npm start
// src/app.jsx中加入const appConfig: IAppConfig = {...icestark: {type: 'framework',Layout: FrameworkLayout,getApps: async () => {const apps = [{path: '/vue',title: 'vue微应用测试',sandbox: false,url: [// 测试环境// 请求子应用端口下的服务,子应用的vue.config.js里面 需要配置headers跨域请求头"http://localhost:3001/js/chunk-vendors.js","http://localhost:3001/js/app.js",],},{path: '/react',title: 'react微应用测试',sandbox: true,url: [// 测试环境// 请求子应用端口下的服务,子应用的webpackDevServer.config.js里面 需要配置headers跨域请求头"http://localhost:3000/static/js/bundle.js",],}];return apps;},appRouter: {LoadingComponent: PageLoading,},},
};
// 侧边栏菜单
// src/layouts/menuConfig.ts 改造const asideMenuConfig = [{name: 'vue微应用测试',icon: 'set',path: '/vue' },{name: 'React微应用测试',icon: 'set',path: '/react'},
]

2. vue子应用接入

# 创建一个子应用
vue create vue-child
// 修改vue.config.jsmodule.exports = {devServer: {open: true, // 设置浏览器自动打开项目port: 3001, // 设置端口// 支持跨域 方便主应用请求子应用资源headers: {'Access-Control-Allow-Origin' : '*','Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS','Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',}},configureWebpack: {// 打包成lib包 umd格式output: {library: 'icestark-vue',libraryTarget: 'umd',},}
}

src/main.js改造

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'import {isInIcestark,getMountNode,registerAppEnter,registerAppLeave,setLibraryName
} from '@ice/stark-app'let vue = createApp(App)
vue.use(store)
vue.use(router)// 注意:`setLibraryName` 的入参需要与 webpack 工程配置的 output.library 保持一致
//  重要 不加不生效 和 vue.config.js中配置的一样
setLibraryName('icestark-vue')export function mount({ container }) {// ![](http://img-repo.poetries.top/images/20210731130030.png)console.log(container,'container')vue.mount(container);
}export function unmount() {vue.unmount();
}if (!isInIcestark()) {vue.mount('#app')
}

router改造

import { getBasename } from '@ice/stark-app';const router = createRouter({// 重要 在主应用中的基准路由base: getBasename(),routes
})export default router

3. react子应用接入

create-react-app react-child
// src/app.jsimport { isInIcestark, getMountNode, registerAppEnter, registerAppLeave } from '@ice/stark-app';export function mount(props) {ReactDOM.render(<App />, props.container);
}export function unmount(props) {ReactDOM.unmountComponentAtNode(props.container);
}if (!isInIcestark()) {ReactDOM.render(<App />, document.getElementById('root'));
}if (isInIcestark()) {registerAppEnter(() => {ReactDOM.render(<App />, getMountNode());})registerAppLeave(() => {ReactDOM.unmountComponentAtNode(getMountNode());})
} else {ReactDOM.render(<App />, document.getElementById('root'));
}

npm run eject后,改造 config/webpackDevServer.config.js

hot: '',
port: '',
...// 支持跨域
headers: {'Access-Control-Allow-Origin' : '*','Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS','Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization',
},

微前端部署

微前端部署实践总结

2022年了你必须要学会搭建微前端项目及部署方式相关推荐

  1. 使用umi4+qiankun 搭建微前端项目

    1.初始化项目: 首先新建空文件夹在里面新建master 文件, 使用一下命令创建主应用; $ yarn create umi ... ✔ Pick Umi App Template › Simple ...

  2. SpringCloud入门总结 + 使用SpringCloud搭建微服务项目

    SpringCloud 1.认识微服务 2.认识spring Cloud 3.Spring Cloud Eureka 服务发现框架 3.1认识Eureka 3.2 实战--开发并部署Eureka Se ...

  3. 基于qiankun搭建ng-alain15微前端项目示例实践

    基础环境 实践日期:2023-03-04 ng versionAngular CLI: 15.2.1 Node: 18.14.2 Package Manager: npm 9.5.0 OS: win3 ...

  4. 基于qiankun搭建ng-alain15微前端项目入门实践

    基础环境 实践日期:2023-02-22 ng versionAngular CLI: 15.1.6 Node: 18.14.2 Package Manager: npm 9.5.0 OS: win3 ...

  5. vue简易微前端项目搭建(一):项目背景及简介

    github传送门: 1.h5主项目 2.项目脚手架 3.子项目模板 系列文章传送门: vue简易微前端项目搭建(一):项目背景及简介 vue简易微前端项目搭建(二):子项目模板及项目脚手架搭建 vu ...

  6. 如何利用qiankun快速搭建一个微前端项目

    前言 小伙伴们大家好.前一篇文章跟大家分享了一些关于微前端的知识点,包括什么是微前端,为什么要用微前端以及如何实现一个微前端,在文章的最后我们还提到了能够实现微前端的两个库:single-spa和qi ...

  7. vue简易微前端项目搭建(二):子项目模板及项目脚手架搭建

    github传送门: 1.h5主项目 2.项目脚手架 3.子项目模板 系列文章传送门: vue简易微前端项目搭建(一):项目背景及简介 vue简易微前端项目搭建(二):子项目模板及项目脚手架搭建 vu ...

  8. VUE项目学习(一):搭建VUE前端项目

    VUE项目学习(一):搭建VUE前端项目 1.安装node.js环境 (1)下载node.js,下载地址为:https://nodejs.org/en/ (2)按照默认选项安装node,检查安装版本 ...

  9. cmd搭建vue前端项目详细过程

    cmd 搭建vue前端项目 下载nods.js node.js下载(Windows版本) next 安装完毕! 配置node.js环境变量 进入找到Path进入 这里填你的node.js的安装路径 验 ...

最新文章

  1. C++与.net的编译方式
  2. 称不上算法的算法-1.简单的高精度计算
  3. golang内置函数
  4. 【Android开发】XML文件解析
  5. java中线程死锁及避免_如何避免Java线程中的死锁?
  6. NFS服务器原理、搭建、配置
  7. 如何检测python是否安装_布同自制Python函数帮助查询小工具
  8. 从ini文件里面读取配置文件
  9. 【python基础知识】对文本数据库的一些基本操作
  10. 如何实现分布式 java_Redis中是如何实现分布式锁的?
  11. 关于word中插入知网e-study插件问题
  12. linux虚拟机怎么显示桌面,虚拟机中如何开启Linux的3d特效桌面?
  13. BC26接入电信云平台流程
  14. unity Debug.DrawLine画线
  15. 微信公众平台开发(PHP)(二) 微信公众平台示例代码分析
  16. unity捕鱼达人3----UI界面的制作以及相关功能的实现
  17. C++ 制作简易音乐播放器
  18. 恶意代码修改IE和注册表恢复全集
  19. 手写call,apply,bind函数
  20. win7系统安装office 2010 visio 出现MSXML安装后依旧无法安装的解决办法

热门文章

  1. 《Python自然语言处理-雅兰·萨纳卡(Jalaj Thanaki)》学习笔记:12 安装指导
  2. 开源项目JCG,运行时json转class并支持添加注解
  3. 飞鸽传书——呼叫系统
  4. Springboot橘子酒店管理系统eg48i计算机毕业设计-课程设计-期末作业-毕设程序代做
  5. java将oracle导出表sql文件中的insert批量更改为update
  6. 八、Linux编辑器之Vi、Vim的使用及技巧篇
  7. 正整数的因子数和因子和
  8. Linux 初始 RAM 磁盘(initrd)概述
  9. Python自动批量修改文件名称的方法大全
  10. css style by alibaba.com