您现在的位置是:亿华云 > 域名

基于 Qiankun 微前端实践- 从零到一篇

亿华云2025-10-03 18:21:06【域名】2人已围观

简介简短的概括:微前端痛点与解决问题1、使用背景1)在同一个页面可以使用多个前端框架(React, AngularJS, Vue 等);2)用新框架编写新代码,无需重写已有的 app;3)代码的延迟加载可

简短的基于概括:微前端痛点与解决问题

1、使用背景

1)在同一个页面可以使用多个前端框架(React, AngularJS, Vue 等);

2)用新框架编写新代码,无需重写已有的前端 app;

3)代码的延迟加载可以缩减初次加载时长;

2、主要解决的问题:

1)在一个 app 中不同的模块由不同的团队维护,而每个团队所用的实践技术栈可能不同,而且发版周期不同。从零

2)所使用的到篇前端框架升级负担,新版本可能存在不兼容的基于更新,升级后可能对已有的前端业务产生 bug,造成难以升级。实践限制了前端框架新版本的从零使用。

一、到篇为什么需要微前端

「~ 微前端导图 ~」

我们通过 3w (what,基于why,how) 的方式来讲解微前端

1、what?前端 什么是微前端?

微前端就是将不同的功能按照不同的维度拆分成多个子应用。通过主应用来加载这些子应用。实践

微前端的从零核心在于拆,拆完后再合!

微前端架构具备以下几个核心价值:(重要)(摘自 qiankun官方文档)

1)技术栈无关

主框架不限制接入应用的到篇技术栈,微应用具备完全自主权;

2)独立开发、源码下载独立部署

微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新;

3)增量升级

在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略;

4)独立运行时

每个微应用之间状态隔离,运行时状态不共享;

2、why? 为什么去使用他?

1)不同团队间开发同一个应用技术栈不同怎么破?

2)希望每个团队都可以独立开发,独立部署怎么破?

3)项目中还需要老的应用代码怎么破?

我们是不是可以将一个应用划分成若干个子应用,将子应用打包成一个个的lib。当路径切换时加载不同的子应用。这样每个子应用都是独立的,技术栈也不用做限制了!从而解决了前端协同开发问题。

3、How? 怎么落地微前端?

2018年 Single-SPA 诞生了,single-spa 是一个用于前端微服务化的 JavaScript 前端解决方案(本身没有处理样式隔离,js 执行隔离)实现了路由劫持和应用加载。

说明:single-spa 解决了以应用为维度的路由,应用的云南idc服务商注册,监听,最重要的是赋予了应用生命周期和生命周期相关事件。

*Single-SPA 缺陷:不够灵活,不能动态加载js文件;样式不隔离,没有js沙箱的机制。

2019年 qiankun 是微前端框架,提供了更加开箱即用的 API (single-spa + sandbox + import-html-entry),它基于 single-spa,具备 js 沙箱、样式隔离、HTML Loader、预加载 等微前端系统所需的能力。qiakun 升级 2.0 后,支持多个微应用的同时加载,有了这个特性,我们基本可以像接入 iframe 一样方便的接入微应用。

*总结:子应用可以独立构建,运行时动态加载,主子应用完全解耦,技术栈无关,靠的是协议接入(子应用必须导出 bootstrap,mount,源码库unmount方法)

扩展:

1)Single-SPA 官网地址:

https://zh-hans.single-spa.js.org/docs/getting-started-overview

2)qiankun官网地址:

https://qiankun.umijs.org/zh

二、解决隔离的方案

1、css 隔离方案

子应用之间样式隔离:

Dynamic Stylesheet 动态样式表,当应用切换时移除老应用样式,添加新应用样式;

主应用和子应用之间的样式隔离:

1)BEM(Block Element Modifier ) 约定项目前缀;

2)css-Modules 打包时生成不冲突的选择器名;

3)Shadow DOM 真正意义上的隔离;

4)css-in-js

2、沙箱 shaowDom

*css 解决方法:

// dom的api

// 外界无法访问 shadow dom

let shadowDOM = document.getElementById(x).attachShadow({ mode: closed});

let pElm = document.createElement(p);

pElm.innerHTML = hello;

let styleElm = document.createElement(style);

styleElm.textContent = `

p{ color: red}

`

shadowDOM.appendchild(styleElm);

shadowDOM.appendchild(pElm);

*JS 沙箱 proxy

快照沙箱简单理解:1年前拍一张 在拍一张 (将区别保存起来) 在回到一年前

源码实践

let sandbox = new SnapshotSandbox();

class SnapshotSandbox{

constructor(){

this.proxy = window; // window属性

this.modifyPropsmap = { }; // 记录在window上的修改

this.active();

}

active() { // 激活

this.windowSnapshot = { }; //拍照

for(const prop in window) {

if(window.hasOwnProperty(prop)){

this.windowsnapshot[prop] = window[prop];

}

}

object.keys(this.modifyPropsMap).forEach(p=>{

window[p] = this.modifyPropsMap[p];

})

}

inactive(){ // 失活

for(const prop in window){

if(window.hasOwnProperty(prop)){

if(window[prop] !== this.windowsnapshot[prop]){

this.modifyPropsMap[prop] = window[prop];

window[prop] = this.windowsnapshot[prop]

}

}

}

}

}

// 应用的运行 从开始到结束, 切换后不会影响全局

((window)=> {

window.a = 1;

window.b = 2;

console.log(window.a,window.b);

sandbox.inactive();

console.log(window.a,window.b);

sandbox.active();

console.log(window.a,window.b);

})(sandbox.proxy); // sandbox.proxy 就是window

// 如果是多个子应用就不能使用这种方式了,es6的proxy

// 代理沙箱可以实现多应用沙箱。把不同的应用用不同的代理来处理

三、qiankun (乾坤) 项目实践

*将普通的项目改造成 qiankun 主应用基座,需要进行三步操作:

1、创建微应用容器 - 用于承载微应用,渲染显示微应用

2、注册微应用 - 设置微应用激活条件,微应用地址等等;

3、启动 qiankun;

扩展:主应用不限技术栈,只需要提供一个容器 DOM,然后注册微应用并 start 即可。

*微前端 qiankun 项目实践:主应用(基座)配置 react 17.0.2,子应用配置 vue 2.6.10

详细配置如下:

1. 主应用(基座)配置 react 17.0.2

1.1 主应用为子应用准备的 展示元素 (文件:src/App.js )

import { BrowserRouter as Router,Link} from react-router-dom

function App() {

return (

vue应用

{ /* 切换导航, 将微应用渲染container容器中 */}

);

}

export default App;

1.2 引入react 渲染,注册 registerApps (文件:src/index.js )

import React from react;

import ReactDOM from react-dom;

import App from ./App;

import ./registerApps

ReactDOM.render(

,

document.getElementById(root)

);

1.3 在主应用中注册微应用(文件:src/registerApps.js)

1、安装 qiankun (建议安装:qiankun 2.X以上,支持多个微应用的同时加载)

yarn add qiankun 或者 npm i qiankun

相关配置信息:

// ------ Step1 引入 qiankun

import { registerMicroApps, start } from qiankun; // 底层是基于single-spa

// ----- Step2 注册子应用

registerMicroApps([{

name: m-vue,

entry: //localhost:20000,

container: #container,

activeRule: /vue,

},

], {

beforeLoad: () => {

console.log(加载前)

},

beforeMount: () => {

console.log(挂在前)

},

afterMount: () => {

console.log(挂载后)

},

beforeUnmount: () => {

console.log(销毁前)

},

afterUnmount: () => {

console.log(销毁后)

},

})

// ----- Step3 启动应用

start();2. 子应用配置 vue 2.6.10

主应用基座只有一个主页,现在我们需要接入微应用。

qiankun 内部通过 import-entry-html 加载微应用,要求微应用需要导出生命周期钩子函数(见下图)。

从上图可以看出,qiankun 内部会校验微应用的生命周期钩子函数,如果微应用没有导出这三个生命周期钩子函数,则微应用会加载失败。

如果我们使用了脚手架搭建微应用的话,我们可以通过 webpack 配置在入口文件处导出这三个生命周期钩子函数。如果没有使用脚手架的话,也可以直接在微应用的 window 上挂载这三个生命周期钩子函数。

2.1 调整子应用 main.js 文件:

import Vue from vue

import App from ./App.vue

import router from ./router

// Vue.config.productionTip = false

let instance = null

function render(props) {

instance = new Vue({

router,

render: h => h(App)

}).$mount(#app); // 这里是挂载到自己的html中 基座会拿到这个挂载后的html 将其插入进去

}

if (window.__POWERED_BY_QIANKUN__) { // 动态添加publicPath

__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;

}

if (!window.__POWERED_BY_QIANKUN__) { // 默认独立运行

render();

}

// 需要暴露接入协议

export async function bootstrap(props) {

console.log([vue] vue app bootstraped);

};

export async function mount(props) {

console.log([vue] props from main framework, props);

render(props);

}

export async function unmount(props) {

instance.$destroy();

instance.$el.innerHTML = ;

instance = null;

router = null;

}

说明:导出相应的生命周期钩子函数。

微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。

*扩展资源:

/

**

* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。

* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。

*/

export async function bootstrap() {

console.log([vue] vue app bootstraped);

}

/

**

* (重要)应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法

*/

export async function mount(props) {

console.log([vue] props from main framework, props);

storeTest(props);

render(props);

}

/

**

* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例

*/

export async function unmount() {

instance.$destroy();

instance.$el.innerHTML = ;

instance = null;

router = null;

}

/

**

* 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效

*/

export async function update(props) {

console.log(update props, props);

}

2.2 新建 vue.config.js,配置如下

module.exports = {

devServer:{

port:10000,

headers:{

// 解决跨域

Access-Control-Allow-Origin:

*

}

},

configureWebpack:{

output:{

// 把子应用打包成 umd 库格式

library: `${ name}-[name]`,

libraryTarget: umd,

jsonpFunction: `webpackJsonp_${ name}`,

}

}

}

*基于 qiankun 微前端项目 (实践代码库)

https://github.com/jiasx/mic-front-vue2.0

https://github.com/jiasx/mic-front-react

很赞哦!(64892)