qiankun
qiankun copied to clipboard
vue3项目,webpackage启用externals,loadMicroApp加载子应用时主应用根节点的内容会被子应用的App.vue替换
现象:
vue3项目,webpackage启用externals,loadMicroApp加载子应用时主应用根节点的内容会被子应用的App.vue替换
- 主应用,子应用的容器id不一致
- 替换的时机发生在子应用bootstrap之前
https://user-images.githubusercontent.com/26342286/139656491-935ca4af-e902-4300-b2ab-d4f975257f37.mp4
- 创建2个空白的vue3应用,分别为主应用和子应用
- 主应用项目改造 · 新建vue.config.js
module.exports = {
configureWebpack: {
externals: {
vue: 'Vue'
}
}
}
- 修改 public/index.html 2.1 引用https://unpkg.com/vue@next 2.2 修改根节点id为"mainApp"
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="mainApp"></div>
<!-- built files will be auto injected -->
</body>
</html>
- 修改 src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#mainApp')
- 修改 src/App.vue
<template>
<div>
<h1>This is Main App!</h1>
<div id="container">
<button @click="load">load micro app</button>
</div>
</div>
</template>
<script>
import { loadMicroApp } from 'qiankun'
export default {
methods: {
load(e) {
e.target.innerHTML = 'loading...'
loadMicroApp({
name: 'microApp',
entry: 'http://localhost:7777/',
container: '#container'
})
}
}
}
</script>
- 子应用项目改造
- 新建vue.config.js
const port = 7777
const name = 'micro'
module.exports = {
configureWebpack: {
externals: {
vue: 'Vue'
},
devServer: {
port,
// 跨域
headers: {
'Access-Control-Allow-Origin': '*',
}
},
output: {
// 把子应用打包成 umd 库格式(必须)
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
}
}
}
- 修改 public/index.html 3.1 子应用根节点id改为"microApp"
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="microApp"></div>
<!-- built files will be auto injected -->
</body>
</html>
- 修改 src/mian.ts
import { createApp } from 'vue'
import App from './App.vue'
let instance: any = null // 根组件实例
async function render(props: any) {
const { container } = props
instance = createApp(App)
instance.mount(container ? container.querySelector('#microApp') : '#microApp')
}
// webpack打包公共文件路径
if (window.__POWERED_BY_QIANKUN__) {
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}
// 生命周期
export async function bootstrap() {
console.log('[vue] vue app bootstraped')
}
export async function mount(props: any) {
console.log('mounted')
console.log('[vue] props from main framework', props)
render(props)
}
export async function unmount() {
console.log('unmounted')
instance.unmount()
}
- 修改 src/App.vue
<template>
<div>this is micro app!</div>
</template>
- 启动两个项目,现象如上面视频所示
##项目依赖 vue: ^3.0.0 qiankun: 2.4.10
备注一点:在禁用了externals之后是正常的
我这边碰到同样的问题。我的场景是因为vue-loader开发环境热更新是通过文件相对路径生成hash值,嵌套子应用的时候hash值相同所以导致主应用被覆盖,设置webpack的mode或者NODE_ENV为production都可以解决