微前端 qiankun vite vue3

文章目录

    • 简介
    • 主应用 qiankun-main vue3 vite
    • 子应用 qiankun-app-vue2 webpack5
    • 子应用 qiankun-react webpack5
    • 子应用 quankun-vue3 vite
    • 遇到的问题

在这里插入图片描述

简介

主要介绍以qiankun框架为基础,vite 搭建vue3 项目为主应用,wepack vue2 和 webpack react 搭建的子应用,形成的一个微前端框架。

主应用 qiankun-main vue3 vite

先用vite 创建一个vue3的标准框架 vue-router typescript 这些都可以选上

yarn create vue

主应用还要装上qiankun依赖

yarn add qiankun

创建一个qiankun-config.ts的文件

import { registerMicroApps, start } from 'qiankun'const beforeLoad: (...args: any[]) => any = (app: any) => {console.log('before load', app)
}
const beforeUnmount: (...args: any[]) => any = (app: any) => {console.log('after unmount', app)
}
const beforeMount: (...args: any[]) => any = (app: any) => {console.log('before mount', app)
}
export function registerApps() {try {registerMicroApps([{name: 'app-vue3', // 子应用名称,跟package.json一致entry: '//localhost:7001', // 子应用入口,本地环境下指定端口container: '#sub-container', // 挂载子应用的domactiveRule: '/app/app-vue3', // 路由匹配规则props: {}, // 主应用与子应用通信传值},{name: 'app-react',entry: '//localhost:3000',container: '#sub-container',activeRule: '/app/app-react',props: {},},{name: 'app-vue2',entry: '//localhost:7003',container: '#sub-container',activeRule: '/app/app-vue2',props: {},}],// 生命周期函数 {beforeLoad: [beforeLoad],beforeMount: [beforeMount],afterUnmount: [beforeUnmount],},)start({sandbox: {experimentalStyleIsolation: true, // 沙箱样式隔离},})} catch (err) {console.log(err)}
}

将上面的文件引入main.ts中

import './assets/main.css'
import { registerApps } from './qiankun-config'
import { createApp } from 'vue'
import { createPinia } from 'pinia'import App from './App.vue'
import router from './router'const app = createApp(App)app.use(createPinia())
app.use(router)app.mount('#qiankun') // 记得把html的挂载id dom改一改registerApps()

创建一个专门用来存放子应用的组件 SubContainer.vue

<script setup lang="ts">
</script><template><h1>Container</h1><div id="sub-container"></div>
</template>

改造主应用的路由router/index.ts

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
// import Layout from '../layout/index.vue'
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: HomeView,},{// history模式需要通配所有路由,详见vue-router文档path: '/app/app-vue3/:pathMatch(.*)*',name: 'app-vue3',meta: {},component: () => import('@/views/SubContainer.vue'),},{path: '/app/app-react/:pathMatch(.*)*',name: 'app-react',meta: {},component: () => import('@/views/SubContainer.vue'),},{path: '/app/app-vue2/:pathMatch(.*)*',name: 'app-vue2',meta: {},component: () => import('@/views/SubContainer.vue'),},],
})export default router

主应用到这里开发环境基本就改造完成了 yarn dev启动开发环境服务器

子应用 qiankun-app-vue2 webpack5

安装vue2 webpack的项目
全局先安装vue-cli

npm install -g @vue/cli
# OR
yarn global add @vue/cli

配置电脑的环境变量 让vscode能够正确使用vue命令符
https://blog.csdn.net/yi_zongjishi/article/details/124831223
上述引用的文章里说以管理员权限启动vscode来处理vscode不能使用vue 的情况有点问题,实际上是以管理员权限启动powershell来执行那些命令后就可以了。

安装vue2框架

vue create qiankun-vue2

安装vue-router
vue2只能安装vue-router@3

yarn add vue-router@3

改webpack的output配置 和devServer配置
由于vue.confg.js存在,所以改造它就等于改造webpack

// const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package')
module.exports = {devServer: {port: 7003, // 与主应用配置子应用的端口号一致就行headers: {'Access-Control-Allow-Origin': '*', // 处理开发环境因为端口号不同而产生的跨域问题},},configureWebpack: {// output为quankun官方要求的必须的output: {library: `${name}-[name]`,libraryTarget: 'umd', // 把微应用打包成 umd 库格式chunkLoadingGlobal: `webpackJsonp_${name}`,},},transpileDependencies: true,
}

根目录下创建一个名为 public-path.js的文件

// 在window上为qiankun挂载关键参数
if (window.__POWERED_BY_QIANKUN__) {// eslint-disable-next-line no-undef__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}

在main.js第一行引入,并对main.js改造

import './public-path'
import Vue from 'vue'
import App from './App.vue'
import router from './router'
// import router from './router'
// import store from './store'Vue.config.productionTip = false // 关闭生产提示let instance = nullfunction render(props = {}) {const { container } = propsinstance = new Vue({router,// store,render: h => h(App)// container 表示 是qiankun主应用访问,限制一下搜索子应用挂载dom的范围,最好能改一下这个id的名称}).$mount(container ? container.querySelector('#vue-app2') : '#vue-app2')
}// 如果不是qiankun主应用下访问,而是子应用独立部署,正常执行render
if (!window.__POWERED_BY_QIANKUN__) {render();
}// 根据qiankun官方要求,子应用需要导出三个生命周期钩子函数bootstrap mount unmount
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() {
// unmount 的时候摧毁掉整个子应用instance.$destroy()instance.$el.innerHTML = ''instance = null
}

记得改掉html文件挂载dom的id为vue-app2

对router.js进行改造

import VueRouter from "vue-router";
import Vue from "vue";
Vue.use(VueRouter);import Home from "./views/Home.vue";
import About from "./views/About.vue";
const routes = [{path: "/",redirect: "/home",},{path: "/home",component: Home,},{path: "/about",component: About,},
];const router = new VueRouter({mode: "history",base: window.__POWERED_BY_QIANKUN__ ? 'app/app-vue2' : '', // 通过qiankun主应用访问子应用时,base需要设置成为主应用专门挂载子用用所在的路径routes,
});export default router;

webpack 5 下的vue2框架项目在开发环境下的改造就差不多完成了。

子应用 qiankun-react webpack5

先从零安装一个react
https://blog.csdn.net/glorydx/article/details/115104561

安装 react-router-dom
改造App.js

import "./App.css";
import About from "./views/About.tsx";
import Home from "./views/Home.tsx";
import { NavLink, useRoutes,  Outlet} from "react-router-dom";
function App() {const base = window.__POWERED_BY_QIANKUN__ ? "/app/app-react/" : "/";const routes = useRoutes([{ path: base, redirect: base + "home", element: <Home /> },{ path: base + "home", element: <Home /> },{ path: base + "about", element: <About /> },]);return (<div className="app"><h1>React Router Dom</h1><div className="main"><div className="leftToolBar"><NavLink to={base + "home"}>Home</NavLink>{/* 或者如下写法传入标签体 */}<NavLink to={base + "about"}>About</NavLink></div><div className="rightContent">{routes}</div></div><Outlet /></div>);
}export default App;

根目录下的 public-path.js

if (window.__POWERED_BY_QIANKUN__) {// eslint-disable-next-line no-undef__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}

改造index.js 最好替换一下挂载的dom id ,同样的需要引入public-path.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import "./public-path.js";
import { BrowserRouter } from "react-router-dom";
function render(props) {const container = props?.container;const root = ReactDOM.createRoot(container? container.querySelector("#app-react"): document.querySelector("#app-react"));root.render(<BrowserRouter><React.StrictMode><App /></React.StrictMode></BrowserRouter>);
}// 然后加入生命周期即可 同样的三个生命周期导出
export async function bootstrap() {console.log("ReactMicroApp bootstraped");
}/*** 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法*/
export async function mount(props) {console.log("ReactMicroApp mount", props);render(props);
}/*** 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例*/
export async function unmount() {console.log("ReactMicroApp unmount");ReactDOM.unmountComponentAtNode(document.getElementById("#app-react"));
}// 如果不是qiankun,正常挂载
if (!window.__POWERED_BY_QIANKUN__) {render();
}
// 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();

改造webpack.config.js 前提是react不会自动暴露这东西,在这之前,你必须执行过 npm run eject 或者yarn eject 去暴露webpack的配置文件

主要是给 output加上qiankun需要的配置

	const packageName = require('../package.json').name;...output: {....library: `${packageName}-[name]`,libraryTarget: 'umd',chunkLoadingGlobal: `webpackJsonp_${packageName}`,},

记得把html挂载的id给换了

<div id="app-react"></div>

如果要引入图片或者其他的什么静态资源
比如react项目本身的logo.svg无法正常显示了
需要在react子项目先把打包方式的hash给干掉
在这里插入图片描述
然后把这个svg不改名的情况下,按照路径给copy到主应用中
在这里插入图片描述
这样qiankun主应用vue3的项目就能正常显示这张图片 如果是其它格式的静态资源也是差不多类似上面的操作

子应用 quankun-vue3 vite

还是同样的方式,先安装一个标准的vite vue3项目 需要有vue-router ts 就行

与webpack 5 的配置方式不同,需要安装依赖 vite-plugin-qiankun
yarn add vite-plugin-qiankun

还是先改造main.ts 记得引入public-path.js 文件内容跟之前一样

import './public-path'
import './assets/main.css'
// alert(1111)
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'let app: any
function render(props = {}) {// 每一次render都需要创建一个新的app = createApp(App)app.use(createPinia()).use(router)const { container } = props as anyapp.mount(container ? container.querySelector('#app-vue3') : '#app-vue3')
}const bootstrap: (...args: any[]) => any = () => {console.log('vue app bootstraped')
}const mount: (...args: any[]) => any = (props) => {const { container } = propsrender(container)console.log('vue3 app mount')
}const unmount: (...args: any[]) => any = () => {app.unmount()
}const initQianKun = () => {// @ts-ignorerenderWithQiankun({mount,bootstrap,unmount,})// render()
}qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()

改造一下router

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
const router = createRouter({history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/app/app-vue3/' : '/'),routes: [{path: '/',redirect: '/home',},{path: '/home',name: 'home',component: HomeView,children: [],},{path: '/about',name: 'about',// route level code-splitting// this generates a separate chunk (About.[hash].js) for this route// which is lazy-loaded when the route is visited.component: () => import('../views/AboutView.vue'),},],
})export default router

配置一下vite.config.ts

import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// import vueDevTools from 'vite-plugin-vue-devtools'
import qiankun from 'vite-plugin-qiankun'
// https://vite.dev/config/
export default defineConfig({plugins: [vue(),// vueDevTools(),qiankun('app-vue3', {useDevMode: true,}),],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url)),},},server: {port: 7001,headers: {'Access-Control-Allow-Origin': '*',},},
})

基本上就改造完成了 然后启动就可以正常访问

遇到的问题

当子应用切换路由后,主应用再切换路由,会报错
当路由发生变化时,触发此pushState函数 ,解决qiankun的一个bug
详情查看 https://blog.csdn.net/chaoPerson/article/details/131398285

解决的办法,如链接所示,在主应用加一个router的hook

router.beforeEach((to, from, next) => {// 当路由发生变化时,触发此pushState函数 ,解决qiankun的一个bug// 详情查看 https://blog.csdn.net/chaoPerson/article/details/131398285if (window.history.state === null) {history.replaceState({back: from.path,current: to.path,forward: null,position: NaN,replaced: false,scroll: null}, 'localhost:5173' + to.path);}next();
});

在子应用当路由变化时 执行 window.history.pushState(null, "", "");
比如react

import { useEffect } from "react";
import "./App.css";
import About from "./views/About.tsx";
import Home from "./views/Home.tsx";
import { NavLink, useRoutes } from "react-router-dom";
function App() {const base = window.__POWERED_BY_QIANKUN__ ? "/app/app-react/" : "/";const routes = useRoutes([{ path: base, redirect: base + "home", element: <Home /> },{ path: base + "home", element: <Home /> },{ path: base + "about", element: <About /> },]);// 当路由发生变化时,触发此pushState函数 ,解决qiankun的一个bug// 详情查看 https://blog.csdn.net/chaoPerson/article/details/131398285useEffect(() => {if(window.__POWERED_BY_QIANKUN__) {window.history.pushState(null, "", "");}}, [routes]);return (<div className="app"><h1>React Router Dom</h1><div className="main"><div className="leftToolBar"><NavLink to={base + "home"}>Home</NavLink>{/* 或者如下写法传入标签体 */}<NavLink to={base + "about"}>About</NavLink></div><div className="rightContent">{routes}</div></div></div>);
}export default App;

比如vue2

<template><div id="app"><h1>qiankun vue2</h1><RouterLink to="/home">home</RouterLink><RouterLink to="/about">about</RouterLink><RouterView /></div>
</template><script>
import {RouterView, RouterLink} from 'vue-router'
export default {name: 'App',components: {RouterView,RouterLink},watch : {$route () {// 当路由发生变化时,触发此pushState函数 ,解决qiankun的一个bug// 详情查看 https://blog.csdn.net/chaoPerson/article/details/131398285if(window.__POWERED_BY_QIANKUN__) {window.history.pushState(null,'','')}}}
}
</script><style>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#从入门到精通(1)

目录 第一章 C#与VS介绍 第二章 第一个C#程序 &#xff08;1&#xff09;C#程序基本组成 1.命名空间 2.类 3.Main方法 4.注释 5.语句 6.标识符及关键字 &#xff08;2&#xff09;程序编写规范 1.代码编写规则 2.程序命名方法 3.元素命名规范 第三章 变量 &…

东隆科技携手PRIMES成立中国校准实验室,开启激光诊断高精度新时代

3月12日&#xff0c;上海慕尼黑光博会期间&#xff0c;东隆科技正式宣布与德国PRIMES共同成立“中国校准实验室”。这一重要合作标志着东隆科技在本地化服务领域的优势与PRIMES在激光光束诊断领域的顶尖技术深度融合&#xff0c;旨在为中国客户提供更快速、更高精度的服务以及本…

HarmonyOS Next~鸿蒙系统架构设计解析:分层、模块化与智慧分发的技术革新

HarmonyOS Next&#xff5e;鸿蒙系统架构设计解析&#xff1a;分层、模块化与智慧分发的技术革新 ​ ​ 鸿蒙操作系统&#xff08;HarmonyOS&#xff09;作为华为自主研发的分布式操作系统&#xff0c;其架构设计以全场景、多设备协同为核心目标&#xff0c;通过分层架构、模…

Vue Router工作原理探究

摘要&#xff1a; 随着单页应用&#xff08;SPA&#xff09;的广泛流行&#xff0c;路由系统成为前端开发中至关重要的部分。Vue Router作为Vue.js官方的路由管理器&#xff0c;为Vue应用提供了强大的路由功能。本文深入探讨Vue Router的工作原理&#xff0c;包括其核心概念、路…

SysOM 可观测体系建设(一):万字长文解读低开销、高精度性能剖析工具livetrace

可观测性是一种通过分析系统输出结果并推断和衡量系统内部状态的能力。谈及可观测性一般包含几大功能&#xff1a;监控指标、链路追踪、告警日志&#xff0c;及 Continues Profiling 持续剖析能力。对于操作系统可观测&#xff0c;监控指标可以帮助查看各个子系统&#xff08;I…

网络安全设备配置与管理-实验4-防火墙AAA服务配置

实验4-p118防火墙AAA服务配置 从这个实验开始&#xff0c;每一个实验都是长篇大论&#x1f613; 不过有好兄弟会替我出手 注意&#xff1a;1. gns3.exe必须以管理员身份打开&#xff0c;否则ping不通虚拟机。 win10虚拟机无法做本次实验&#xff0c;必须用学校给的虚拟机。首…

路由Vue Router基本用法

路由的作用是根据URL来匹配对应的组件&#xff0c;并且无刷新切换模板的内容。vue.js中&#xff0c;可使用Vue Router来管理路由&#xff0c;让构建单页应用更加简单。 一、效果 二、实现 1.项目中安装Vue Router插件 pnpm install vue-routerlastest 2.main.js import { …

24. 状态模式

原文地址: 状态模式 更多内容请关注&#xff1a;智想天开 1. 状态模式简介 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态改变时改变其行为&#xff0c;使得该对象看起来似乎修改了其类。状态模式通过将状态的行…

【Qt】Qt + Modbus 服务端学习笔记

《Qt Modbus 服务端学习笔记》 1.因为项目的需要&#xff0c;要写一个modbus通信&#xff0c;csdn上感觉有些回答&#xff0c;代码是人工智能生成的&#xff0c;有些细节不对。我这个经过实测&#xff0c;是可以直接用的。 首先要包含Qt 的相关模块 Qt Modbus 模块主要包含以…

CherryStudio + 火山引擎DeepSeek R1 告别服务器繁忙

CherryStudio 火山引擎DeepSeek R1 告别服务器繁忙 一、下载CherryStudio并安装 CherryStudio是功能强大的多模型桌面客户端&#xff0c;支持Windows、macOS和Linux系统。集成了多种主流的大语言模型&#xff08;如OpenAI、DeepSeek、Gemini等&#xff09;以及本地模型运行功…

医院人事科室病区管理系统基于Spring Boot-SSM

目录 摘要 一、研究背景与意义 二、国内外研究现状 三. 系统目标 四、研究目的与内容 五、研究方法与技术路线 5.1 系统技术架构 六. 系统功能 6.1 人事管理 6.2 科室病区管理 6.3 科研管理 七. 系统安全性 八. 系统运行与维护 摘要 随着医疗行业的快速发展和医院…

Unity TextMeshPro中显示建筑特殊符号

示例&#xff1a;显示效果如图 实现步骤 1、下载 SJQY 字体库 2、导入字体&#xff1a;将 SJQY 字体文件&#xff08;如 .ttf 或 .otf 文件&#xff09;导入到 Unity 项目的 Assets 文件夹中。 3、创建 TMP 字体资产 方法一 方法二 选择刚导入的字体文件&#xff0c;在…

工具层handle_excel

该工具类利用openpyxl的load_workbook加载Excel&#xff0c;通过iter_rows按行迭代数据&#xff0c;将表头和用例数据用zipdict组合成字典&#xff0c;通过list.append将字典(单条测试用例)追加到列表中&#xff0c;从而封装Excel数据解析工具。 模块/类方法/属性使用场景描述o…

九、JavaScript作用域、预解析

一、JavaScript作用域 1.JavaScript作用域 ①代码名字&#xff08;变量&#xff09;在某个范围内起作用和效果 目的是为了提高程序的可靠性更重要的是减少命名冲突 ②js的作用域&#xff08;es6&#xff09;之前&#xff1a;全局作用域 局部作用域 ③全局作用域&#xff1a;整…

Rust语言学习

Rust语言学习 通用编程概念所有权所有权引用和借用slice struct(结构体)定义并实例化一个结构体使用结构体方法语法 枚举 enums定义枚举match控制流运算符if let 简单控制流 使用包、Crate和模块管理不断增长的项目&#xff08;模块系统&#xff09;包和crate定义模块来控制作用…

Windows Docker 报错: has no HTTPS proxy,换源

pull python 3.7报错&#xff1a; 尝试拉取Docker 测试库hello world也失败 尝试使用临时镜像源&#xff0c;可以成功拉取&#xff1a; sudo docker pull docker.m.daocloud.io/hello-world说明确实是网络问题&#xff0c;需要配置镜像源&#xff0c;为了方便&#xff0c;在d…

Git远程拉取和推送配置

Git进行远程代码拉取和推送时候提示配置user.name 和 user.email 背景&#xff1a;换新电脑后使用Git进行代码拉取和推送过程中&#xff0c;提示“Make sure you configure your “user.name” and “user.email” in git.”。这个配置针对git的正常使用仅需要配置一次&#xf…

详解string类+迭代器

迭代器 概念&#xff1a;在 C 中&#xff0c;迭代器是访问容器&#xff08;如数组、列表、向量、字符串等&#xff09;元素的一种方式。迭代器提供了一种统一的接口&#xff0c;使得你可以使用相同的代码来遍历不同类型的容器。迭代器本质上是一个指针或者指针的封装&#xff0…

小红书不绑定手机号会显示ip吗

小红书作为一个生活方式分享平台&#xff0c;拥有庞大的用户群体。在小红书上&#xff0c;用户可以分享自己的生活点滴、购物心得、美食体验等&#xff0c;与其他用户进行互动交流。最近&#xff0c;不少用户对于小红书是否会在不绑定手机号的情况下显示IP属地产生了疑问&#…

Web-Machine-N7靶机实战攻略

1.安装并开启靶机 下载VirtualBox&#xff1a;https://www.virtualbox.org 导入虚拟机 设置为桥接模式 2.获取靶机IP Kali设为桥接模式 3.访问靶机 4.获取敏感目录文件和端口 gobuster dir -u http://172.16.2.68 -w /usr/share/wordlists/dirbuster/directory-list-2.3-me…