介绍
qiankun 是一个基于 single-spa 的微前端实现库,旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。
什么是微前端
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。
微前端架构具备以下几个核心价值:
- 技术栈无关
主框架不限制接入应用的技术栈,微应用具备完全自主权- 独立开发、独立部署
微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新- 增量升级
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略- 独立运行时
每个微应用之间状态隔离,运行时状态不共享
快速上手
主应用
1. 安装 qiankun
npm i qiankun -S
2. 在主应用中注册微应用
//main.js import { registerMicroApps, start } from 'qiankun'; registerMicroApps([{ name: 'sub1', entry: 'http://localhost:9003',//子应用等启用地址 container: '#container',//子应用所展示的地址,在app.vue中设置的ID activeRule: '/sub1',//路由地址 props: { navName: '123', id: 11 } }, { name: 'sub2', entry: 'http://localhost:9002', container: '#container', activeRule: '/sub2', props: { navName: '345', id: 22 } }, ]); start();
//app.vue <template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/sub1">about</router-link> | <router-link to="/sub2">sub2</router-link> </div> <router-view/> <div id="container"></div> </div> </template>
微应用
1.在 src 目录新增 public-path.js
if (window.__POWERED_BY_QIANKUN__) { __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__; }
2.main.js 修改
vue2
import './public-path'; import VueRouter from 'vue-router' import routes from './router'; Vue.use(VueRouter) let router = null; let instance = null; function render(props = {}) { const { container } = props; router = new VueRouter({ base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/', mode: 'history', routes, }); instance = new Vue({ router, store, render: (h) => h(App), }).$mount(container ? container.querySelector('#app') : '#app');//主应用中设置的id } // 独立运行时 if (!window.__POWERED_BY_QIANKUN__) { render(); } export async function bootstrap() { 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() { instance.$destroy(); instance.$el.innerHTML = ''; instance = null; router = null; }
vue3
import { createApp } from 'vue' import {createRouter,createWebHistory} from 'vue-router' import App from './App.vue' import routes from './router' let app let router let history function render(props = {}){ history = createWebHistory('/vue') router = createRouter({ history, routes }) app = createApp(App) const {container} = props app.use(router).mount(container?container.querySelector('#app'):'#app') } if(!window.__POWERED_BY_QIANKUN__){ render() } // 子组件暴露三个函数 export async function bootstrap(props){ console.log('我是bootstrap项目函数',props); } export async function mount(props){ console.log('我是mount项目函数',props); render(props) } export async function unmount(props){ console.log('我是vue项目unmount函数',props); history = null app = null router = null }
vue3不再new Vue了,而是使用createApp,注意和vue2有所区别
3.router路由配置
//router/index.js const routes = [{ path: '/', name: 'About', component: () => import ('../views/About.vue') }] export default routes
4.打包配置修改vue.config.js
风格一
const { name } = require('./package'); module.exports = { devServer: { headers: { 'Access-Control-Allow-Origin': '*', }, }, configureWebpack: { output: { library: `${name}-[name]`, libraryTarget: 'umd', // 把微应用打包成 umd 库格式 jsonpFunction: `webpackJsonp_${name}`, //webPack5中删除了此属性 }, }, };
风格二
const { defineConfig } = require('@vue/cli-service') module.exports = defineConfig({ transpileDependencies: true, publicPath:'http://localhost:8083', configureWebpack:{ output:{ library:'vueApp', libraryTarget:'umd' } }, devServer:{ port:8083, headers:{ 'Access-Control-Allow-Origin':'*' } }, })
旧版本的webpack可能会报错defineConfig,可以去掉difineConfig(),只保留{}中的内容,或者升级新版webpack。
publicPath中的port和devServer中port中保持一致,可以根据你的项目修改。