微前端(qiankun)vue2、vue3+webpack、vue3+vite的详细使用
微前端 qiankun 是一个基于Single-SPA框架开发的、开源的微前端实现库,由蚂蚁金服(现蚂蚁集团)团队开发和维护。它的目标是为开发者提供一套简单、强大且生产可用的解决方案,帮助构建大型单页应用或聚合多个独立前端应用,无视框架限制React、Vue、Angular 等。
目录
一、什么是qiankun
微前端 qiankun 是一个基于 Single-SPA 框架开发的、开源的微前端实现库,由蚂蚁金服(现蚂蚁集团)团队开发和维护。它的目标是为开发者提供一套简单、强大且生产可用的解决方案,帮助构建大型单页应用或聚合多个独立前端应用,无视框架限制React、Vue、Angular 等。
二、应用
主应用 vue3+Ts+vite
主应用是所以子应用的出口,也可以说是一个容器。在各个子应用中起着协调、布局的作用。可以React、Vue、Angula框架作为主应用的框架。
这里主应用就使用Vu3+Ts+vite作为主应用的项目框架,首先初始一个主应用项目:
npm create vite@latest
安装路由:
npm i vue-router -S
主应用必须安装 qiankun
npm i qiankun -S
注册子应用:main.ts
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import router from './router';
// 引入qiankun
import { registerMicroApps, start } from 'qiankun';
// 进行子应用的注册
registerMicroApps([
{
name: 'son-vue2', // 取自子应用 package.json 文件中的name属性,必填
entry: '//localhost:3001', // 子应用端口
container: '#qiank-container', // 子应用挂载的dom
activeRule: '/vue2', // 子应用的路由入口
props: {} // 传给子应用的数据,可以传递一些主应用初始化全局性的数据,比如语言、全局配置,其他数据的传递后续咱们使用发布订阅的形式来完成
},
{
name: 'son-vue3-webpack',
entry: '//localhost:3002',
container: '#qiank-container',
activeRule: '/vue3-webpack',
props: {}
},
{
name: 'son-vue3-vite',
entry: '//localhost:3003',
container: '#qiank-container',
activeRule: '/vue3-vite',
props: {}
}
]);
start({
sandbox: {
//启用沙箱样式隔离
experimentalStyleIsolation: true
}
});
createApp(App).use(router).mount('#app');
子应用的入口可以随意给我这里直接写在App.vue的文件了
<template>
<div>
<router-link to="/vue2">子应用(vue2)</router-link>
|
<router-link to="/vue3-webpack">子应用(vue3-webpack)</router-link>
|
<router-link to="/vue3-vite">子应用(vue3-vite)</router-link>
</div>
<h1>以下为子应用内容:</h1>
<!-- qiank-container这个必须跟注册时候的一直 -->
<div id="qiank-container"></div>
</template>
主应用配置完成
子应用1 vue2+webpack
vue2
创建项目
vue create son-vue2
修改 vue.config.js
const { defineConfig } = require('@vue/cli-service');
const { name } = require('./package.json');
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 3001, //与主应用的注册端口号一直
headers: {
'Access-Control-Allow-Origin': '*' //设置为允许跨域
}
},
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd', //设置umd格式
// webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
chunkLoadingGlobal: `webpackJsonp_${name}`
}
}
});
新建 src/public-path.js
文件
if (window.__POWERED_BY_QIANKUN__) {
//以下注释是为了避开eslint报错
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
修改 main.js
文件,qiankun
要求子应用在其入口文件中正确导出特定的生命周期函数,其实就是要导出这三个函数:bootstrap/mount/unmount
import './public-path.js';
import Vue from 'vue';
import App from './App.vue';
Vue.config.productionTip = false;
let instance = null;
function render(props = {}) {
console.log('子应用(vue2)', props);
const { container } = props;
instance = new Vue({
render: h => h(App)
}).$mount(container ? container.querySelector('#app') : '#app');
}
// 非qiankun环境下,也能独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
/**
* bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
* 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
*/
export async function bootstrap() {}
/**
* 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
*/
export async function mount(props) {
render(props);
}
/**
* 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
*/
export async function unmount() {
instance.$destroy();
instance.$el.innerHTML = '';
instance = null;
}
子应用2 Vue3+webpack
修改 vue.config.js
:跟vue2一样
const { defineConfig } = require('@vue/cli-service');
const { name } = require('./package.json');
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
port: 3002,
headers: {
'Access-Control-Allow-Origin': '*'
}
},
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',
// webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
chunkLoadingGlobal: `webpackJsonp_${name}`
}
}
});
新建 src/public-path.js
文件:
if (window.__POWERED_BY_QIANKUN__) {
//以下注释是为了避开eslint报错
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
修改 main.js
文件
import './public-path.js';
import { createApp } from 'vue';
import App from './App.vue';
let appInstance = null;
/**
* 渲染主应用或微应用
* @param {Object} props - 微应用传递的 props(如 container)
*/
const render = (props = {}) => {
const { container } = props;
const mountTarget = container?.querySelector('#app') || '#app';
try {
appInstance = createApp(App);
appInstance.mount(mountTarget);
} catch (error) {
console.error('渲染失败:', error);
}
};
/**
* 微应用生命周期:初始化(仅一次)
*/
export async function bootstrap() {
console.log('[微应用] bootstrap');
}
/**
* 微应用生命周期:挂载(每次进入调用)
*/
export async function mount(props) {
console.log('[微应用] mount', props);
render(props);
}
/**
* 微应用生命周期:卸载(每次切出调用)
*/
export async function unmount() {
if (appInstance) {
appInstance.unmount(); // Vue 3 使用 unmount 替代 $destroy
appInstance._container.innerHTML = ''; // 清理 DOM 残留
appInstance = null;
console.log('[微应用] unmount 完成');
}
}
// 独立运行(非 qiankun 环境)
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
子应用3 vue3+vite+Ts
启动项目:
npm create vite@latest
安装 vite-plugin-qiankun 依赖,它能帮助咱们快速接入 qiankun 环境:
npm install vite-plugin-qiankun -D
修改mian.ts
import { createApp } from 'vue';
import './style.css';
import App from './App.vue';
import {
renderWithQiankun,
qiankunWindow
} from 'vite-plugin-qiankun/dist/helper';
let app: any = undefined;
const render = (props: any) => {
console.log('子应用(son-vue3-vite)', props);
const { container } = props;
app = createApp(App);
app.mount(container ? container.querySelector('#app') : '#app');
};
const initQianKun = () => {
renderWithQiankun({
bootstrap() {},
mount(props) {
render(props);
},
unmount() {
app.unmount();
},
update() {}
});
};
qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render({});
三、结果
更多推荐
所有评论(0)