前一篇文章讲了qiankun集成vue子应用,这篇随笔讲集成react子应用。
1、创建react子应用
用react脚手架初始化一个react项目,至于项目的数据仓库store和路由、以及UI组件库这里就不做讲解,可以自己自行网上找资料配置。
create-react-app my-react-app
2、在src路径下创建publicPath.js文件,内容和上一篇的vue子应用一致,这里不再说了,不清楚请翻我上一篇随笔
3、下面是react项目的入口js的内容,针对这js做下讲解
import React, { Suspense } from "react"; import ReactDOM from "react-dom/client"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; import { HashRouter, BrowserRouter } from "react-router-dom"; import { Spin, ConfigProvider } from "antd"; import { store, persistor } from "./store"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; import zhCN from "antd/locale/zh_CN"; import "./publicPath.js"; let mountNode = null; let root = null; function render(props) { const { container } = props; mountNode = container ? container.querySelector("#root") : document.querySelector("#root"); root = ReactDOM.createRoot(mountNode); root.render( <ConfigProvider locale={zhCN}> <Provider store={store}> <PersistGate loading={null} persistor={persistor}> <Suspense fallback={<Spin size="large" style={{ marginTop: 100 }} />}> <BrowserRouter basename={window.__POWERED_BY_QIANKUN__ ? "/app-react/" : "/"} > <App /> </BrowserRouter> </Suspense> </PersistGate> </Provider> </ConfigProvider> ); } if (!window.__POWERED_BY_QIANKUN__) { render({}); } export async function bootstrap() { console.log("[react16] react app bootstraped"); } export async function mount(props) { console.log("[react16] props from main framework", props); render(props); } export async function unmount(props) { root.unmount(); } reportWebVitals();
这里绝大部分和vue一致,也是新增一个render函数,用于区分是从qiankun框架访问还是直接访问,里面的创建react实例根据react的版本可能稍有不同,我这边使用的是18.2.0,路由是react-router-dom的BrowserRouter,是
history模式,这里也要设置路由的base,这里和vue一致,然后下面暴露三个方法,也和上一篇的vue一致,只不过unmount方法用的是react的卸载,这个是react18.2.0的卸载方法,官网用的是unmountComponentAtNode,可能
这个方法目前已经废弃,如果你用的react是17版本以前的可以使用,如果是17之后的或者最新的就用我上面的这个。
3、最后是打包,修改webpack配置,这里使用的是官网推荐的@rescripts/cl,首先安装插件依赖
yarn add -D @rescripts/cli
然后在项目根目录下新增.rescriptsrc.js文件,文件内容如下
const { name } = require("./package"); module.exports = { webpack: (config) => { config.output.library = `${name}-[name]`; config.output.libraryTarget = "umd"; // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal config.output.chunkLoadingGlobal = `webpackJsonp_${name}`; config.output.globalObject = "window"; return config; }, devServer: (_) => { const config = _; config.headers = { "Access-Control-Allow-Origin": "*", }; // config.historyApiFallback = true; // config.hot = false; // config.watchContentBase = false; // config.liveReload = false; return config; }, };
主要有个打包配置,这里注意一下jsonFunction和chunkLoadingGlobal的区别,webpack4使用jsonFunction,webpack5则用chunkLoadingGlobal,下面就是headers的配置,防止跨域csp的问题,这点和上一篇的vue里面是一样的。
到这里react子应用就配置好了,下面就是在主应用注册子应用,如下:
//注册微服务应用 registerMicroApps([ { name: "vueApp", entry: "//localhost:8080", container: "#micro-app-container", activeRule: "/app-vue", }, { name: "reactApp", entry: "//localhost:3000", container: "#micro-app-container", activeRule: "/app-react", }, ]);
第一个是上一篇的vue子应用,下面的就是我们刚刚创建的子应用,到这里就完成了整个react子应用的集成。
下面是我在主应用的App.vue里面的代码片段,点击vue子应用跳转vue子应用,点击react子应用跳转react子应用。
<template> <div id="app"> <div class="chunk-menu"> <div class="chunk-menu-item" :class="[activeApp == 1 ? 'active-menu' : '']" @click="handleChange(1)" > vue子应用 </div> <div class="chunk-menu-item" :class="[activeApp == 2 ? 'active-menu' : '']" @click="handleChange(2)" > react子应用 </div> </div> <img alt="Vue logo" src="./assets/logo.png" /> <div id="micro-app-container"></div> </div> </template> <script> export default { name: "App", components: {}, data() { return { activeApp: "", }; }, methods: { handleChange(type) { this.activeApp = type; switch (type) { case 1: //vue this.$router.push("/app-vue/"); break; case 2: //react this.$router.push("/app-react/"); break; } }, }, }; </script>
补:这里会有一个问题,假如点击同一个路由的话可能会报异常,这个是vue-router的bug,可以在主应用的router文件里解决,解决方案放在下面,主要是Vue.use(Router)下面的
import Vue from "vue"; import Router from "vue-router"; Vue.use(Router); const originalPush = Router.prototype.push; // 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题 Router.prototype.push = function push(location) { return originalPush.call(this, location).catch((err) => err); };
标签:qiankun,vue,架构,app,react,应用,import,config From: https://www.cnblogs.com/zhouyun-yx/p/18246190