微前端Webpack集成Vite子应用避坑指南

目录

1、Vite和qiankun框架的兼容性问题

2、vite-plugin-qiankun插件的使用

简介

快速开始

3、子应用集成的页面不断刷新,不显示页面的问题

[4、Uncaught (in promise) ReferenceError: global is not defined](#4、Uncaught (in promise) ReferenceError: global is not defined)

5、子应用跨域问题

6、本地连调时,静态资源404无法获取的问题

7、父子微前端应用接口代理冲突问题

8、globalState问题

9、React多自定义render页,在qiankun框架内找不页面的问题。


1、Vite和qiankun框架的兼容性问题

2024/12/30,目前qiankun框架官方还未完全适配vite应用。通过qiankun集成vite子应用还需使用对应的插件,若直接按qiankun官网来进行配置,很可能会报以下错误:

[import-html-entry]: error occurs while executing normal script ...

这是因为vite底层是通过script标签的module形式来进行加载的,而qiankun框架默认不支持这种方式。解决方案见2。

2、vite-plugin-qiankun插件的使用

这个插件可以解决vite使用qiankun集成的问题,详见:

https://www.npmjs.com/package/vite-plugin-qiankun

注意事项:

(1)这个插件虽然可以解决大体上的问题,但仍然遗留了隐患,使用该插件会破坏qiankun原有的沙箱环境,可能导致一些页面参数的冲突。

(2)本地连调时记得开启useDevMode = true ,否则可能出现反复刷新页面不显示的问题。

(3)qiankunWindow.POWERED_BY_QIANKUN 可用于判断是否为qiankun子应用时的环境,设置basename时很有用:

//window.INJECTED_ROUTER_BASE_BY_QIANKUN 这个全局参数是父应用自定义的子应用访问前缀,在父应用中声明即可。

html 复制代码
<BrowserRouter

          basename={

            qiankunWindow.__POWERED_BY_QIANKUN__

              ? // qiankun 子应用时

              `${window.INJECTED_ROUTER_BASE_BY_QIANKUN || ''}/`

              : // 非 qiankun 子应用时

              '/'

          }

        >
简介

vite-plugin-qiankun: 帮助应用快速接入乾坤的vite插件

  • 保留vite构建es模块的优势

  • 一键配置,不影响已有的vite配置

  • 支持vite开发环境

快速开始

1、在 vite.config.ts 中安装插件

// vite.config.ts

import qiankun from 'vite-plugin-qiankun';

export default {

// 这里的 'myMicroAppName' 是子应用名,主应用注册时AppName需保持一致

plugins: [qiankun('myMicroAppName')],

// 生产环境需要指定运行域名作为base

base: 'http://xxx.com/'

}

2、在入口文件里面写入乾坤的生命周期配置

// main.ts

import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

// some code

renderWithQiankun({

mount(props) {

console.log('mount');

render(props);

},

bootstrap() {

console.log('bootstrap');

},

unmount(props: any) {

console.log('unmount');

const { container } = props;

const mountRoot = container?.querySelector('#root');

ReactDOM.unmountComponentAtNode(

mountRoot || document.querySelector('#root'),

);

},

});

if (!qiankunWindow.POWERED_BY_QIANKUN) {

render({});

}

3、dev下作为子应用调试

因为开发环境作为子应用时与热更新插件(可能与其他修改html的插件也会存在冲突)有冲突,所以需要额外的调试配置

// useDevMode 开启时与热更新插件冲突,使用变量切换

const useDevMode = true

const baseConfig: UserConfig = {

plugins: [

...(

useDevMode ? [] : [

reactRefresh()

]

),

qiankun('viteapp', {

useDevMode

})

],

}

上面例子中 useDevMode = true 则不使用热更新插件,useDevMode = false 则能使用热更新,但无法作为子应用加载。

4、其它使用注意点 qiankunWindow

因为es模块加载与qiankun的实现方式有些冲突,所以使用本插件实现的qiankun微应用里面没有运行在js沙盒中。所以在不可避免需要设置window上的属性时,尽量显示的操作js沙盒,否则可能会对其它子应用产生副作用。qiankun沙盒使用方式

import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

qiankunWindow.customxxx = 'ssss'

if (qiankunWindow.POWERED_BY_QIANKUN) {

console.log('我正在作为子应用运行')

}

3、子应用集成的页面不断刷新,不显示页面的问题

(1)插件未开启useDevMode = true;

(2)entry对应子应用服务器的路径不对,如:

{

name: 'child-micro-app',

entry:

process.env.NODE_ENV === 'development' ? '//localhost:4000' : '/page', // 当页面处于生产环境时,同域名下,若没有 /page的页面对应该子应用的服务器页面,则可能会出现该异常。

},

4、Uncaught (in promise) ReferenceError: global is not defined

这个问题一般出现这vite项目环境中,一般中入口文件中配置如下,即可解决vite项目中global的问题,但集成到父应用时也可能报该异常,此时,需要在父项目的入口文件中也配置该global对象:

javascript 复制代码
(window as any).global = window;

5、子应用跨域问题

(1)当entry为另一个域名的微前端应用时,需要考虑跨域问题,如:

entry: "https://other.example.com" // 和当前域名不同时。

可以在Nginx下配置以下参数:

add_header 'Access-Control-Allow-Origin' 'https://允许跨域的域名.com';

(2)子应用的有些接口跨域,可能需要在父应用中配置代理来解决。

6、本地连调时,静态资源404无法获取的问题

vite子应用的资源,本地直接子父应用中访问可能出现资源根域名仍然是父应用根域名的情况。

解决方案有两个:

(1)建立一个公共的资源地址,让父子应用都从里面获取静态资源;

(2)vite本地连调时,配置origin:

export default defineConfig(({ mode }) => ({

server: {

//用于定义开发调试阶段生成资源的 origin。

origin: 'http://localhost:4000', // 子应用的ip和端口

......

线上时,配置base为子应用当前域名:

// qiankun生产环境需要指定运行域名作为base

// base: 'https://child.domain.com',

7、父子微前端应用接口代理冲突问题

问题描述:父应用localhost:8070,子应用localhost:4000,它们都使用自己独立的/api代理,当子应用集成到父应用中时,子应用发出的/api即可被父应用的/api代理提前拦截代理掉,导致子应用代理的路径不对的问题。

解决方案:

(1)子应用配置baseUrl:

javascript 复制代码
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper';

// 被qiankun集成作为子应用时baseUrl是/childApi,单独访问时是/api

const baseUrl = qiankunWindow.__POWERED_BY_QIANKUN__ ? "/childApi/api" : '/api';

(2)父应用配置对应的代理,如:

javascript 复制代码
"/childApi/": {  // 子应用对应/api代理的写法

target: "子应用/api代理的target",

changeOrigin: true,

pathRewrite: {'^/childApi': ''},

}

(3)也可将baseUrl写死为绝对路径,如:http://localhost:8000/api,但这样会造成诸多不便,不推荐。

注意,有时配置可能会少写/api这样的访问路径,导致接口报405或404,检查接口是否在正确的路径上。

8、globalState问题

有时,子应用可能需要一些全局参数,若子应用调用了,但没有,可能会报错。以下是gloablState的案例代码:

(1)父应用中设置,当然,你也可以自定义优化一下

javascript 复制代码
import {registerMicroApps, start, initGlobalState} from 'qiankun';

// 全局状态管理

const state = {count: 1};

const action = initGlobalState(state);

action.onGlobalStateChange((value, prev) => {

 console.log('main app change', value, prev);

});

action.setGlobalState(state);

(2)子应用中获取

javascript 复制代码
​
let app: any;

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {

 createApp(App).use(router).use(ElementPlus).mount('#app');

} else {

 renderWithQiankun({

   mount(props) {

     app = createApp(App).use(router).use(ElementPlus);

     app.mount(props.container?.querySelector('#app'));

     console.log('vue app mount get props', props);

     props.onGlobalStateChange((state: any, prev: any) => console.log(`子应用 [onGlobalStateChange - ${props.name}]:`, state, prev));

     props.setGlobalState({count: 100});

   },

     // bootstrap、update、unmount三个生命周期省略。。。。

 });

}

​

9、React多自定义render页,在qiankun框架内找不页面的问题。

问题描述:子应用有多个root.render页面,用于处理不同的渲染逻辑,直接访问子应用的这些页面,一切正常;但在父应用中访问某些页面时,页面找不到了。经过控制台打印检查,发现子应用根本没有走自定义render页的逻辑,连自定义html里script module也未使用。检测发现,qiankun框架直接选择了react里src/main.tsx作为了入口文件,其他的直接没检测到,这是问题的原因。

解决方案:在src/main.tsx里配置对应的自定义render逻辑,如:

javascript 复制代码
import goCustomRender from './app/custom/main';

const goMainRender = () => {

let root: ReactDOM.Root;

function render(props: any) {

........

  }

renderWithQiankun({

.......

});

if (!qiankunWindow.__POWERED_BY_QIANKUN__) {

  render({});

}

}

// 在父应用中设置window.GO_CUSTOM_PAGE全局参数为true,即可表示需要走自定义render逻辑

if (window.GO_CUSTOM_PAGE) {

goCustomRender()

} else {

goMainRender()

}

解决以上问题,基本可以成功配置完毕子应用为vite的应用,亲测有效!

相关推荐
前端青山5 分钟前
JavaScript闭包的深度剖析与实际应用
开发语言·前端·javascript·前端框架·ecmascript
JINGWHALE18 分钟前
设计模式 结构型 组合模式(Composite Pattern)与 常见技术框架应用 解析
前端·人工智能·后端·设计模式·性能优化·系统架构·组合模式
青颜的天空16 分钟前
CSS 中 content换行符实现打点 loading 正在加载中的效果
前端·css
凌小添19 分钟前
Python教程丨Python环境搭建 (含IDE安装)——保姆级教程!
开发语言·python·教程
DX_水位流量监测25 分钟前
水库水位监测系统的自动化功能:减少人工干预,可实现实时监控
运维·前端·人工智能·自动化·制造·信息与通信·零售
代码驿站52040 分钟前
PHP语言的数据库编程
开发语言·后端·golang
m0_548503031 小时前
打包部署若依(RuoYi)SpringBoot后端和Vue前端图文教程
前端·vue.js·spring boot
阿芯爱编程1 小时前
清除数字栈
java·服务器·前端
花菜会噎住1 小时前
Python 模块,包(详解)
开发语言·python
kittygilr1 小时前
matlab中几个取整函数的区别
开发语言·matlab