date
slug
status
tags
type
avatar
summary

微前端概念

  1. 类似 <iframe></iframe> 一样,只不过微前端是用fetch去请求js并渲染在指定的DOM容器。
  1. 跟技术栈无关,任何前端技术栈都可以接入。
  1. 多个应用结合在一起,可以一起运行,又可以单独运行。
  1. 一个复杂庞大的项目拆成多个微应用,单独开发、单独部署、单独测试,互不影响。
  1. 原理是通过在主应用引入每个子应用的入口文件(main.js),进行解析,并指定渲染的容器(DOM),其次每个子应用设置打包的文件为UMD,然后在main.js暴露(export)生命周期方法(bootstrapmountunmount),然后再其mount进行渲染,也就是new Vue(...),并在unmount执行destory

微前端的应用

  • 类似于ERP系统。
  • 庞大的系统需要拆分给不同团队去做时。
  • 系统里面有很多个模块,模块里面又很多个子模块时。

QianKun 常用API介绍

  • registerMicroApps(apps, lifeCycles?) 自动挡加载模块,一次性写好配置,直接传入,然后调用start()qiankun会自动监听url变化调用对应的应用暴漏的生命周期函数。
  • start(opts?) 配合registerMicroApps使用,当调用registerMicroApps后,运行启动。
  • loadMicroApp(app, configuration?) 手动加载模块,需要自己监听Url并手动加载模块。
  • addGlobalUncaughtErrorHandler(handler)/removeGlobalUncaughtErrorHandler(handler) 添加/移除监听应用加载错误。
  • initGlobalState(state) 初始化全局共享状态,类似于vuex,返回三个个方法,分别是setGlobalState(state)onGlobalStateChange((newState, oldState) => {})
    • setGlobalState(state) 设置全局状态
    • onGlobalStateChange((newState, oldState) => {}) 监听全局状态变化
具体可以查看QianKun文档

具体实施

Qiankun ├─ common // 存放公共方法(store,utils,主应用与微应用通信,axios) ├─ main // 主应用 └─ micro // 微应用 ├─ react-app └─ vue3-app

主应用配置

npm install qiankun
main.js
import { registerMicroApps, start } from 'qiankun'; // 注册微应用 registerMicroApps([ { name: 'vue', entry: '//localhost:3000', container: '#vue-app', // 和app.vue配置的节点 activeRule: '/vue', props: { msg: "我是来自主应用的值-vue" // 主应用向微应用传递参数 } }, { name: 'react', entry: '//localhost:5174', container: '#react-app', // 和app.vue配置的节点 activeRule: '/react', props: { msg: "我是来自主应用的值-react" // 主应用向微应用传递参数 } } ]); // 启动 qiankun start();
App.vue
<template> <RouterView /> <div id="vue-app"></div> <div id="react-app"></div> </template>

微应用配置

vue3+vite
npm 安装 npm i vite-plugin-qiankun qiankun
vite.conf.js配置
import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' import qiankun from 'vite-plugin-qiankun' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ vue(), vueJsx(), qiankun('vue', { // 微应用名字,与主应用注册的微应用名字保持一致 useDevMode: true }), ], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } }, css: { preprocessorOptions: { scss: { additionalData: '@import "@/assets/scss/global.scss";' } } }, server: { port: '3000' } })
main.js
import 'normalize.css/normalize.css' import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' import router from './router' import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper' const initQianKun = () => { renderWithQiankun({ // 当前应用在主应用中的生命周期 // 文档 https://qiankun.umijs.org/zh/guide/getting-started# mount(props) { console.log(111, props) render(props.container) // 可以通过props读取主应用的参数:msg // 监听主应用传值 props.onGlobalStateChange((res) => { // store.count = res.count console.log(res) }) }, bootstrap() { }, unmount() { }, }) } const render = (container) => { // 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地 const appDom = container ? container : "#app" const app = createApp(App) app.use(createPinia()) app.use(router) app.mount(appDom) } console.log('vue', qiankunWindow.__POWERED_BY_QIANKUN__) // 判断当前应用是否在主应用中 qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()
这里有个处理的点,由于我主应用和子应用都是用的vue3+vite的方式,同名文件生成的hash是一样的,导致样式会覆盖,这里我改动了微应用的@vitejs/plugin-vue这个文件的源码,使用打补丁的方式
npm i patch-package
npx patch-package 依赖名称
根目录下会生成一个patches文件夹,我给所有的hash都加了个vue的后缀,然后重新目录就可以看到hash更改了,后面就可以愉快的更改节点的样式了,不用担心覆盖
notion image
之前搜了很多方式,都没法满足我的需求,就自行实验了这个,后面优化可以弄成脚本的形式,省去查找文件然后一个一个添加
react+vite
npm 安装 npm i vite-plugin-qiankun qiankun
vite.conf.js
import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import qiankun from 'vite-plugin-qiankun' // https://vitejs.dev/config/ export default defineConfig({ plugins: [ // vite react qiankun下开发者模式需要把这个注释,否则会报错无法启动 // react(), qiankun('react', { // 微应用名字,与主应用注册的微应用名字保持一致 useDevMode: true }) ], })
这里开发环境需要把react()这个方法注释,否则会报错
notion image
main.js
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper' const initQianKun = () => { renderWithQiankun({ // 当前应用在主应用中的生命周期 // 文档 https://qiankun.umijs.org/zh/guide/getting-started# mount(props) { render(props.container) // 可以通过props读取主应用的参数:msg // 监听主应用传值 props.onGlobalStateChange((res) => { console.log(res.count) }) }, bootstrap() { }, unmount() { }, }) } const render = (container) => { // 如果是在主应用的环境下就挂载主应用的节点,否则挂载到本地 const appDom = container ? container : document.getElementById('root') ReactDOM.createRoot(appDom).render( <React.StrictMode> <App /> </React.StrictMode> ) } // 判断当前应用是否在主应用中 qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()

common文件夹常用方法 — 待更新

全局状态通讯
store
layout
axios
utils

qiankun部署 — 待更新

github主从仓库使用
QianKun
Big-xiongUpdated Oct 7, 2023
Gitlab-RunnerCss3变量的使用