主题
微前端应用(一)
本页对应 微前端应用,共 5 段视频,约 1 小时 0 分。
学习目标
- 能够按“先技术 Demo、后业务改造”的流程完成 2D 图表接入,并说明初始化需在 DOM 宽高可用后执行的原因。
- 能够将一个独立业务逻辑拆分为
useXxx组合式函数,并在组件中导入、执行、解构使用其返回的数据和方法。 - 能够说明 3D 需求从产品对接、建模、后端接口到前端解析渲染的完整流程,并指出前端主要负责的环节。
- 能够使用大屏适配插件包裹可视化主体容器,按 1920×1080 基准尺寸配置并验证不同屏幕比例下的缩放与留白效果。
- 能够说明采用微前端的项目背景与收益,并在主应用中完成乾坤注册子应用、配置入口地址、挂载节点和激活路由。
- 能够完成子应用接入乾坤的插件配置、静态资源路径配置和生命周期钩子注册,并验证通过激活路由成功加载子应用及触发挂载钩子。
知识点
先明确主应用改造的目标
这一节做的是“主应用改造”,主应用指后台管理项目,子应用指前台可视化大屏项目。改造后希望达到的效果是:在主应用里访问某个约定路由时,乾坤把子应用加载进来,并渲染到主应用预留的容器中,看起来像主应用的一个页面。
为什么需要这样做?因为两个项目技术栈和职责不同,主应用不能直接把子应用代码复制进来,而是要通过微前端框架做“注册、激活、挂载”。怎么想?先不要急着写业务,按乾坤的要求把主应用侧四件事做好:装包、写注册配置、入口启动、准备挂载节点。怎么做?下面按步骤展开。易错点是:所有操作都在主应用里做,不要跑到子应用项目里装包和写注册文件。
安装乾坤
为什么需要?主应用要使用 registerMicroApps、start 等能力,必须先安装 qiankun。怎么想?按官网快速上手,先完成依赖安装,再写配置。怎么做?在主应用根目录执行:
bash
npm i qiankun易错点:转写稿里反复强调“不要装错位置”,要在后台管理这个主应用里安装,不要装到前台子应用里。装完后可以检查主应用 package.json 是否出现 qiankun 依赖。
新增微应用注册配置文件
为什么需要?乾坤需要知道子应用叫什么、从哪里加载、挂到哪个容器、访问哪个路由时激活。怎么想?把注册逻辑单独放到一个文件里,入口只负责引入,结构更清晰。怎么做?在主应用里新增配置文件,例如 registerMicroApp.js,写入笔记中的代码:
javascript
import { registerMicroApps, start } from 'qiankun'
registerMicroApps([
{
name: 'hmzs-big-screen', // 子应用名称
entry: '//localhost:5173', // 子应用运行服务地址(就是npm run dev时的那个地址)
container: '#container', // 挂载容器(id=container)
activeRule: '/big-screen' // 激活路由(在哪个路由下加载子应用,需要和子应用的路由名称对应)
}
])
start()这里四个配置要理解:name 是子应用名称,后续子应用侧配置要能对应;entry 是子应用 npm run dev 后实际运行的地址,转写稿中强调“你的是啥就是啥,不要写死”,如果端口从 5173 变成 5174,就要同步改;container 是主应用里准备好的挂载节点选择器,笔记里是 #container;activeRule 是激活路由,访问 /big-screen 时才加载子应用。
易错点:start() 不能漏;container 的 id 要和模板里的 id 一致;activeRule 一般带前导斜杠;entry 写错会导致资源加载不到。转写稿里还提醒:本节只做主应用侧配置,子应用侧还需要配套改造,否则实际加载可能不成功。
入口文件启动配置
为什么需要?只新增注册文件不会自动执行,必须在入口文件里引入,让注册和启动逻辑生效。怎么想?把微前端配置当作一个启动模块,在 main.js 中导入即可。怎么做?在主应用入口文件加入:
javascript
// 启动微前端配置
import './registerMicroApp'易错点:引入路径要跟实际文件名一致;不要只写配置不引入;引入位置放在主应用入口中,不要放到子应用入口里。
配置子应用渲染位置
为什么需要?乾坤加载子应用后,需要一个真实 DOM 节点承接渲染。怎么想?在主应用 App.vue 的模板中,保留原有 router-view,再在旁边准备一个 id="container" 的节点。怎么做?按笔记写入:
vue
<template>
<div id="app">
<router-view />
<!-- 子应用挂载节点 -->
<div id="container" />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>易错点:id="container" 必须与注册配置里的 container: '#container' 对应;不要把挂载节点写成子应用内部节点;如果主应用自身路由也会占用页面区域,要确认访问 /big-screen 时该节点存在。
联调与调试过程
完成以上配置后,主应用和子应用都要启动。转写稿中的调试方式是:先启动子应用,确认其地址,例如 //localhost:5173;再启动主应用;然后在主应用浏览器地址中访问 /big-screen。当路径匹配 activeRule 后,乾坤会去 entry 加载子应用资源,并渲染到 #container。如果页面没有出现,优先检查四件事:主应用是否安装了 qiankun;注册文件是否被入口引入;entry 端口是否与子应用实际启动地址一致;#container 是否真实存在。控制台若有加载或挂载信息,也可以辅助判断是否触发了加载。易错点仍是“主应用配置不要写到子应用里”,以及端口、路径、id 三处必须对应。
一、子应用为什么要改造
qiankun 默认并不支持 Vite 项目直接作为子应用,它更习惯 Webpack 那套加载方式。因此,前台可视化项目要被后台主应用加载,不能只保证“自己能跑”,还要让主应用能够接管它的启动、挂载和资源加载。转写稿里把这件事说得很直白:子应用被主应用加载过去之后,它的静态资源如果还按默认方式走,就可能走到主应用地址上,导致图片 404。所以子应用改造的核心不是写业务,而是解决三件事:插件支持、资源路径、生命周期暴露。
改造顺序可以记成:先装 vite-plugin-qiankun,再改 vite.config,最后改入口文件。易错点是:不要只改主应用,子应用也必须改;配置里的 name 必须和主应用注册子应用时的 name 保持一致。
二、安装并配置 vite-plugin-qiankun
为什么需要?因为 Vite 项目默认没有 qiankun 需要的子应用接入约定,插件负责把这层桥接起来。怎么想?把插件注册到 Vite 的 plugins 中,并告诉它“我这个子应用叫什么”。这个名字不是随便写着玩的,主应用要靠它识别子应用。怎么做?先在子应用里安装:
bash
npm i vite-plugin-qiankun -D然后修改 vite.config.js:
javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun'
export default defineConfig({
base: '/',
plugins: [
vue(),
// 这里的名称要和主应用改造是配置项中的name保持一致
qiankun('hmzs-big-screen', {
useDevMode: true
})
],
server: {
// 防止开发阶段的assets 静态资源加载问题
origin: '//localhost:5173'
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
}
}
})这里的 server.origin 是调试时很容易漏掉的点。转写稿解释得很清楚:子应用被主应用加载后,代码里引用的图片等资源,如果不加这个配置,可能会按主应用的地址去请求,例如走到主应用的端口下找 assets,但图片实际在子应用端口下,于是加载失败。加上 origin,就是强制开发阶段的静态资源仍然走子应用自己的地址。
易错点有三个:qiankun('hmzs-big-screen') 里的名字要和主应用配置一致;origin 的端口要和你实际启动子应用的端口一致,转写稿示例是 5173,如果你启动成了 5174,这里也要改;useDevMode: true 是开发模式下的配置,联调时要注意主、子应用都正常启动。
三、改造入口文件:暴露 qiankun 生命周期
为什么需要?qiankun 加载子应用时,不是简单打开一个页面,而是调用子应用暴露的生命周期,例如 bootstrap、mount、unmount。Vite 默认入口通常是直接 createApp(App).mount('#app'),这不能满足被主应用接管的需求。怎么想?用 renderWithQiankun 注册生命周期,在 mount 时执行渲染;同时保留独立运行能力:如果没有被 qiankun 接管,就自己渲染。怎么做?把入口改成:
javascript
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import './styles/common.scss'
// 使用乾坤渲染
renderWithQiankun({
// 挂载时
mount (props) {
console.log('mount')
render(props)
},
bootstrap () {
console.log('bootstrap')
},
unmount (props) {
console.log('unmount', props)
},
})
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render({})
}
function render (props = {}) {
const { container } = props
const app = createApp(App)
app.use(router)
app.mount(container ? container.querySelector("#app") : "#app")
}这段代码的关键在 render:被主应用加载时,props.container 是主应用提供的容器,子应用不能直接找全局 #app,而要在 container.querySelector("#app") 里挂载;独立运行时没有 container,才挂到页面的 #app。转写稿中的调试过程是:入口加入 mount 打印后,在主应用访问配置的激活路由,子应用被加载,控制台能看到“子应用完成挂载”一类信息,说明生命周期被调用了。
易错点:container 可能为空,所以要判断;querySelector("#app") 的选择器要和子应用模板里的挂载点对应;不要在被 qiankun 加载时又重复执行独立渲染。笔记里的 unmount 只做了打印,实际项目若需要清理定时器、事件等,应在该钩子里补充清理逻辑。
四、联调验证与常见问题
改造完成后,先启动子应用,再启动主应用,在主应用中访问配置好的激活路由,例如转写稿演示的 big-screen。qiankun 会去子应用地址加载资源,并把子应用渲染到主应用指定的容器节点中。验证时重点看三处:页面是否出现在主应用容器里;控制台是否打印 mount;Network 里图片等静态资源是否走子应用端口。
常见问题按顺序排查:主应用注册的 name 与子应用插件名是否一致;主应用 entry 是否写成子应用实际启动地址;主应用挂载节点 ID 是否和配置一致;子应用 server.origin 是否配置;激活路由是否匹配。只要激活路由能正常把子应用加载过来,并且资源不 404,本节改造就算完成。
按钮跳转要解决什么:给后台主应用一个进入大屏的入口
为什么需要:后台管理项目和大屏可视化项目组合后,用户不能每次都手动改地址栏进入大屏。转写稿里的演示目标是:在后台主应用上放一个“打开大屏”的按钮,点击后把前台可视化子应用加载到主应用界面中,效果类似一级路由。因此这个按钮本质上是“主应用进入子应用”的入口。
怎么想:入口要放在用户容易看到、又不破坏顶栏布局的位置。笔记选择放在头像/用户信息区域 avatar-wrapper 中,按钮和“黑马管理员”并排。点击时不做整页刷新,而是用 Vue Router 的 $router.push('/big-screen') 改变路由,让主应用进入 /big-screen,再由微前端配置匹配激活路由并加载子应用。
怎么做:在头像区域加入 el-button,保留用户名称,代码如下:

vue
<div class="avatar-wrapper">
<el-button size="small" plain
@click="$router.push('/big-screen')">可视化大屏</el-button>
<!-- 用户名称 -->
<span class="name">黑马管理员</span>
</div>易错点:路径要写完整、拼写一致,/big-screen 不要少斜杠;模板里是 $router.push,不是 $route.push,$route 是当前路由信息对象,没有 push 方法;按钮要放在 avatar-wrapper 内,别放错到其他布局容器导致样式错位。
路由跳转只是第一步:还要和乾坤的激活路由对齐
为什么需要:点击按钮只是让地址栏变成 /big-screen,页面是否真的出现大屏,还取决于主应用里注册微应用时的“激活路由”是否匹配。转写稿中配置乾坤时强调:当访问某个路由时,才去加载子应用;演示时手动访问 big-screen 能触发加载。因此按钮路径和激活路由必须是一套规则。
怎么想:把链路拆成三段:按钮负责“改路由”;主应用路由/乾坤配置负责“识别 /big-screen 并加载子应用”;子应用负责“被挂载到指定容器”。转写稿里还提到 entry 要写子应用启动地址、container 要写挂载节点 id,这些配置错了,按钮点了也可能空白。
怎么做:检查主应用注册微应用配置中激活路由是否匹配 /big-screen;检查 entry 是否指向子应用实际启动地址,例如转写稿中演示过 5173,如果端口变成 5174 就要同步改;检查挂载节点 id 是否与 container 一致;子应用侧配置的 name 要与主应用注册名保持一致。
易错点:转写稿里的“情况/勤坤/清空”实际都是 qiankun(乾坤),不要被同音字带偏;激活路由多一个斜杠、少一个斜杠都可能不匹配;子应用端口变化后忘记改 entry;主应用挂载节点 id 和配置不一致。
调试与验证:点击后分层排查
为什么需要:按钮跳转不生效时,可能是按钮事件、路由路径、乾坤配置、子应用资源加载中的任意一层问题。转写稿中通过控制台观察子应用挂载日志来验证效果,这种分层排查最稳。
怎么想:先看点击后地址栏有没有变成 /big-screen;再看主应用是否识别该路由并请求子应用资源;最后看子应用是否执行挂载。转写稿视频5里在子应用入口加了生命周期打印,出现“子应用完成挂载”说明挂载成功。
怎么做:点击“可视化大屏”按钮,观察地址栏;打开控制台看是否有子应用挂载日志;看网络面板是否加载子应用资源;若图片等静态资源 404,按转写稿提示检查子应用静态资源路径配置,避免被主应用地址接管。
易错点:不要只看页面空白就判断按钮没生效;改完子应用配置要重启;控制台报错要区分是路由未匹配还是资源加载失败。
本节要解决的问题
这一节的核心不是讲复杂配置,而是讲一个最容易忽略、却最影响调试的前提:主应用要能加载子应用,子应用必须已经运行,并且主应用里的 entry 必须和子应用实际运行地址严格一致。原笔记只有两条检查点:第一,测试时保证子应用项目已经 run 起来,因为主应用需要从子应用服务拉取资源;第二,子应用 run 的服务地址要和主应用中的 entry 选项严格保持一致,尤其注意端口号。本节笔记未附图片和代码,下面用转写稿中的操作过程补足推导与排查思路。
知识点一:先启动子应用,再访问主应用
为什么需要:微前端里主应用并不是把子应用代码提前打包进自己,而是在运行时根据 entry 去子应用服务请求入口资源和后续静态资源。子应用没启动,主应用就“拉不到资源”,页面自然挂不出来。
怎么想:把子应用当成一个独立服务,把主应用当成容器。容器再完整,被装载的服务没开,也拿不到内容。转写稿中把前台、后台两个项目放到同一文件夹,分别开终端执行 npm run dev,确认两个项目都能正常跑起来,之后才进入微前端改造。这个顺序就是本节要强调的顺序。
怎么做:先进入子应用目录启动服务,例如:
bash
npm run dev看终端输出的本地地址,并先用浏览器直接访问这个地址,确认子应用自己能打开;再启动主应用;最后访问主应用中配置的激活路由,观察子应用是否被加载。转写稿中演示输入激活路由后,子应用被拉取并渲染到主应用指定节点,控制台还打印了“子应用完成挂载”,这就是一个可验证信号。
易错点:只启动主应用,不启动子应用;子应用启动失败但主应用只显示空白;两个终端目录进错;子应用被关闭后主应用刷新失败;端口被占用后子应用自动换端口,但主应用配置没跟着改。
知识点二:entry 必须与子应用实际运行地址严格一致
为什么需要:entry 是主应用拉取子应用资源的入口。它写错,主应用就会去错误地址请求,出现连接失败、404 或资源加载失败。
怎么想:不要凭记忆写地址,要以子应用终端实际输出为准。转写稿中主应用配置子应用时,entry 配的是 http://localhost:5173;也提醒,如果连续启动两次,端口可能从 5173 变成 5174,那 entry 也要改成 5174。这就是“严格一致”的含义:协议、主机、端口都要对得上。
怎么做:先看子应用终端输出的 Local 地址;再到主应用注册子应用的配置中检查 entry;确认两者完全一致。转写稿中主应用配置项还包括子应用名字、挂载节点、激活路由:entry 决定“从哪里拉”,名字决定“认哪个子应用”,挂载节点决定“挂到哪里”,激活路由决定“什么时候拉”。这几项要联动检查。
易错点:端口写死;localhost 和 127.0.0.1 混用;http 与 https 混用;子应用端口自动切换后没改 entry;改完配置没重启主应用或没刷新页面;挂载节点 id 写错,导致“资源加载了但没挂上”。
调试顺序建议
建议按这个顺序排查:第一,子应用单独启动并能浏览器访问;第二,主应用启动;第三,核对 entry 与子应用实际地址;第四,访问激活路由;第五,打开 Network 和 Console 看请求是否打到正确端口;第六,若端口变化,同步修改 entry 后重启或刷新。转写稿中还提到静态资源路径问题:子应用被主应用加载后,图片等静态资源不能错误地走主应用地址,否则会 404。这个问题虽然不属于“子应用是否运行”本身,但调试时经常一起出现,检查 entry 时也要顺手确认静态资源请求地址是否正确。
先明确:container 是子应用的“落点”
本节笔记的核心只有一句:作为子应用的挂载节点,也就是 container 容器要准备好,否则没有挂载的位置。
为什么需要: 微前端改造里,主应用负责“准备位置”,子应用负责“提供内容”。qiankun 加载子应用后,不是凭空把页面画出来,而是要把子应用渲染到主应用中一个真实存在的 DOM 节点里。这个节点就是 container 对应的容器。没有它,子应用即使被加载了,也没有地方落。
怎么想: 不要把 container 只理解成配置项。它有两层含义:一层是注册微应用时写的选择器,例如 container: '#big-container';另一层是主应用模板里真实存在的 <div id="big-container"></div>。配置项指向节点,节点承接渲染,两者必须对上。
怎么做: 先确定子应用要显示在主应用哪个位置,再在那里准备一个 div,给它一个唯一 id。转写稿里的做法是:在主应用 App.vue 的一级路由旁边准备挂载节点,id 写成 big-container,注册配置里用 #big-container 去匹配。
易错点: 只写了注册配置,却没有在页面里放节点;或者节点 id 与配置选择器不一致;或者把 id 写成 class,导致选择器对不上。容器没准备好,后面 entry、activeRule 配得再对,也没有落点。
在主应用模板里准备挂载节点
为什么需要: qiankun 最终要把子应用内容塞进主应用的某个 DOM 位置。这个位置必须真实存在,并且最好在子应用加载前就已经渲染出来。
怎么想: 转写稿里没有把节点随便塞进子应用,而是在主应用里准备。因为主应用是壳,子应用是被加载进来的内容。节点应该放在主应用稳定存在的区域,例如一级路由旁边,而不是放在会被频繁销毁重建的条件渲染块里。
怎么做: 按转写稿整理,主应用模板中可准备类似节点:
vue
<template>
<div id="app">
<!-- 主应用原有内容 -->
<div id="big-container"></div>
</div>
</template>这里的 id="big-container" 要与注册配置里的 container: '#big-container' 对应。转写稿强调“ID 的名字要跟这个地方的名字匹配上”。
易错点: 节点 id 重复;节点被 v-if 控制导致加载时不存在;把节点写到子应用内部;只写 big-container 却漏了配置里的 #。这些都会让 qiankun 找不到挂载位置。
把 container 写进微应用注册配置
为什么需要: 主应用需要知道“加载哪个子应用、从哪里加载、挂到哪里、什么时候激活”。container 就是其中的“挂到哪里”。
怎么想: 转写稿里主应用新增了一个注册微应用的文件,从 qiankun 导入注册子应用的方法和启动方法,然后配置 name、entry、container、activeRule。其中 name 可以随便取,但要和子应用插件配置保持一致;entry 是子应用启动地址;container 是挂载节点选择器;activeRule 是激活路由。
怎么做: 按转写稿整理成示意配置:
js
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'big-screen',
entry: '//localhost:5173',
container: '#big-container',
activeRule: '/big-screen',
},
]);
start();然后在主应用 main.js 中导入这个注册文件,让配置生效。转写稿特别提醒:这个文件写完不会自动生效,需要在入口里引入。
易错点: entry 写成主应用端口 8081,而子应用实际是 5173;子应用端口变了却写死旧端口;container 写成 big-container 漏 #;activeRule 与访问地址不匹配;注册文件没在 main.js 引入,导致配置完全不执行。
联调验证:访问激活路由,看容器是否被使用
为什么需要: 容器准备是否正确,不能只看代码,要看运行结果。qiankun 只有在 activeRule 匹配后,才会去 entry 加载子应用,并渲染到 container 指定位置。
怎么想: 转写稿的调试过程是:主应用和子应用都启动,主应用访问 /big-screen,路由匹配后触发加载,子应用资源被拉过来,最终渲染到 id 为 big-container 的节点里。视频 5 还通过 mount 生命周期打印“子应用完成挂载”来验证。
怎么做: 先启动主应用和子应用,确认子应用地址;在主应用地址后访问激活路由;打开 Elements 看 #big-container 下是否出现子应用内容;看控制台是否有挂载生命周期输出。若没有内容,优先检查节点是否存在、id 是否匹配、entry 端口是否写对、activeRule 是否匹配。
易错点: 只改配置不重启;子应用端口变化后没同步 entry;访问的路由不是 activeRule;容器节点存在但被样式遮挡或宽高异常。调试时先确认“节点在不在”,再确认“配置指没指对”,最后确认“路由有没有激活”。
代码示例
1. 主应用(后台管理)注册微应用 + 挂载容器 + 跳转按钮
javascript
// src/registerMicroApp.js —— 主应用新增文件
import { registerMicroApps, start } from 'qiankun'
registerMicroApps([
{
name: 'hmzs-big-screen', // 子应用名称(必须和子应用 qiankun() 第一个参数一致)
entry: '//localhost:5173', // 子应用运行服务地址(就是 npm run dev 时的地址)
container: '#container', // 挂载容器(id=container)
activeRule: '/big-screen' // 激活路由,需要和子应用的路由名称对应
}
])
start()javascript
// src/main.js —— 在原有入口文件里加一行,启动微前端配置
import './registerMicroApp'vue
<!-- src/App.vue —— 准备子应用挂载节点 -->
<template>
<div id="app">
<router-view />
<!-- 子应用挂载节点 -->
<div id="container" />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>vue
<!-- 大屏入口按钮 -->
<div class="avatar-wrapper">
<el-button size="small" plain
@click="$router.push('/big-screen')">可视化大屏</el-button>
<!-- 用户名称 -->
<span class="name">黑马管理员</span>
</div>要点解释 / 易错点
registerMicroApps收的是数组,可以注册多个子应用;本节只有一个。name是主、子应用之间的唯一约定,主应用写'hmzs-big-screen',子应用qiankun()里就必须是'hmzs-big-screen',两边不一致就加载不上。entry必须和子应用npm run dev时真实打印的地址严格一致(含端口号);端口被占用自动变 5174 时,这里也要跟着改,不能写死。container: '#container'要求 App.vue 里真有id="container"的节点,否则没有挂载位置,页面一片空白。activeRule: '/big-screen'是"开关":主应用地址栏访问/big-screen时才会去拉子应用资源;按钮$router.push('/big-screen')正是为了触发它。- 测试前子应用必须已经 run 起来,因为主应用是从子应用服务实时拉资源的,子应用没启动主应用只会报加载失败。
2. 子应用(前台可视化)vite 配置接入 qiankun 插件
javascript
// vite.config.js —— 子应用
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun'
export default defineConfig({
base: '/',
plugins: [
vue(),
// 这里的名称要和主应用配置项中的 name 保持一致
qiankun('hmzs-big-screen', {
useDevMode: true
})
],
server: {
// 防止开发阶段的 assets 静态资源加载问题
origin: '//localhost:5173'
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
}
}
})要点解释 / 易错点
- qiankun 默认不支持 Vite 项目作为子应用,必须先装
vite-plugin-qiankun并在plugins中注册,否则子应用根本进不了乾坤的生命周期。 qiankun()的第一个参数是子应用名,务必与主应用registerMicroApps里的name完全一致(包括大小写、连字符)。server.origin: '//localhost:5173'是本节最容易漏的一行:子应用被主应用加载后,代码里assets下的图片等静态资源会**走主应用地址(如 8081)**去找,必然 404;加上它强制静态资源仍走子应用自己的地址。- 改完 vite 配置要重启子应用 dev 服务才生效。
3. 子应用入口文件改造(交给乾坤接管挂载/卸载)
javascript
// src/main.js —— 子应用
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import './styles/common.scss'
// 使用乾坤渲染
renderWithQiankun({
// 挂载时
mount (props) {
console.log('mount')
render(props)
},
bootstrap () {
console.log('bootstrap')
},
unmount (props) {
console.log('unmount', props)
},
})
// 独立运行(没有被乾坤接管)时,自己挂载
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {
render({})
}
function render (props = {}) {
const { container } = props
const app = createApp(App)
app.use(router)
app.mount(container ? container.querySelector('#app') : '#app')
}要点解释 / 易错点
- 原来入口里那句
createApp(App).mount('#app')要删掉,改由renderWithQiankun的mount生命周期接管,否则会被挂载两次。 render里的三元判断是关键:被乾坤加载时props.container有值,要挂到主应用传进来的容器里的#app上;独立运行(npm run dev单跑)时没有container,就挂到自己的#app。if (!qiankunWindow.__POWERED_BY_QIANKUN__) render({})这行不能删,删了以后单独启动子应用就是白屏。- 想在被主应用成功挂载后做点事(埋点、初始化图表等),写在
mount里即可;卸载清理写在unmount里。 - 子应用被主应用加载时,控制台应能看到
bootstrap → mount的打印顺序,可作为"接进去了"的验证信号。
常见错误
主应用输入激活路由后白屏,控制台报子应用资源 404
- 现象:访问
/big-screen时容器区域空白,Network 中子应用的 HTML/JS 全部 404 或 CORS 报错。 - 原因:
entry与子应用实际 dev 服务地址不一致(端口被占用后 Vite 自动切到 5174,而entry仍写 5173),或子应用项目根本没启动。 - 修法:先确认子应用终端输出的实际端口,同步修改
entry;把entry抽成环境变量,避免手写死端口;联调前先单独打开//localhost:5173验证子应用可独立运行。
- 现象:访问
子应用挂载成功但页面无样式/图片全部裂开
- 现象:子应用内容渲染出来了,但背景图、icon 全部加载失败,Network 里图片请求指向主应用端口(如 8081)。
- 原因:子应用被主应用接管后,相对路径的静态资源会基于主应用地址解析;Vite 配置里缺少
server.origin,且base未设为/。 - 修法:
server.origin写成子应用自身地址//localhost:5173,base: '/',静态资源用绝对或@/assets别名引用,改完重启 dev server。
控制台报
Application died in status LOADING_SOURCE_CODE或renderWithQiankun is not a function- 现象:主应用注册成功但加载子应用时直接失败,或子应用入口报导入错误。
- 原因:子应用是 Vite 项目,未装
vite-plugin-qiankun,或装了但没在vite.config的plugins里注册,或入口仍用原生createApp().mount()而没有走renderWithQiankun。 - 修法:安装插件并在
plugins中注册(名称与主应用name完全一致、useDevMode: true),入口改为renderWithQiankun({ mount, bootstrap, unmount })+ 独立运行兜底if (!qiankunWindow.__POWERED_BY_QIANKUN__) render({})。
主应用
name与子应用插件name不一致导致加载异常- 现象:子应用能拉取到资源,但生命周期不触发、
mount不打印,或反复加载卸载。 - 原因:
registerMicroApps里的name与qiankun('xxx')的字符串不匹配,qiankun 无法把应用与生命周期对应起来。 - 修法:两处字符串严格一致(建议抽成共享常量/环境变量),改名后两端都要重启。
- 现象:子应用能拉取到资源,但生命周期不触发、
报
Target container with #container not existed- 现象:路由跳转后控制台报容器不存在,子应用不渲染。
- 原因:
container: '#container'对应的 DOM 节点没在App.vue模板里写,或写在router-view之外的条件分支/v-if里导致加载时不存在。 - 修法:在根组件模板中常驻一个
<div id="container" />,不要加v-if,位置放在需要展示的区域。
子应用独立运行时正常,嵌入后重复挂载 / 内存泄漏
- 现象:来回切换路由后页面出现两份内容,或事件监听重复触发。
- 原因:
mount中每次都createApp但unmount里没有app.unmount(),实例未销毁。 - 修法:把
app提到模块级变量,mount时创建并赋值,unmount中执行app.unmount()并置空,必要时清理定时器与事件监听。
练习
把主应用中
registerMicroApps的配置抽成独立模块,name、entry、activeRule改为从环境变量读取,并说明为什么entry不适合硬编码端口。子应用当前在
mount里只打印日志,请补全unmount逻辑,使路由来回切换 5 次后 DOM 中始终只有一份子应用内容,并在控制台验证挂载/卸载次数对应。故意把子应用的
server.origin注释掉,启动两个项目并进入/big-screen,用 Network 面板定位图片请求的错误地址,然后修复并复述原因。在子应用中新增一个页面(如
/detail),验证:主应用进入/big-screen后子应用内部路由跳转是否正常、浏览器刷新后主应用能否重新正确加载子应用。给主应用加一个"退出大屏"按钮,点击后回到后台首页,观察子应用是否被正确卸载,并记录控制台生命周期打印顺序(bootstrap → mount → unmount)。
课堂画面






原视频对照
| # | 视频 | 时长 |
|---|---|---|
| 1 | 重点内容回顾 | 20:34 |
| 2 | 使用插件做大屏适配 | 10:40 |
| 3 | 微前端背景说明 | 08:54 |
| 4 | 微前端主应用乾坤配置 | 10:27 |
| 5 | 微前端子应用乾坤配置 | 09:33 |
小结
- 主应用只做三件事:装 qiankun、写注册配置、在入口引入并准备好挂载容器,其余交给 qiankun 调度。
- 子应用改造成本更高,Vite 项目必须依赖
vite-plugin-qiankun,入口要从createApp().mount()换成renderWithQiankun生命周期写法。 name(主应用配置)与qiankun('name')(子应用插件)必须完全一致,entry必须与子应用实际运行地址完全一致,这两处是最容易出错的地方。activeRule是"开关":只有主应用路由命中时才会拉取并渲染子应用,容器节点必须常驻存在。server.origin与base: '/'是解决子应用静态资源走错主应用域名/端口的关键配置,漏配的典型表现是图片全裂。- 子应用入口必须保留
qiankunWindow.__POWERED_BY_QIANKUN__判断,保证既能被主应用接管,也能独立开发调试。 - 调试顺序固定为:先单独跑通子应用 → 再跑主应用 → 最后联调激活路由,出问题先看 Network 的地址和端口。
- 微前端适用于多技术栈共存、需共享登录态的较大型项目;小团队、单体项目强行接入只会增加改造成本与通信复杂度。