qiankun搭建

以react为主应用

1.创建项目

新建一个文件夹

create-react-app qiankun-base
create-react-app qiankun-micro-app1
create-react-app qiankun-micro-app1

qiankun搭建_第1张图片

2.安装qiankun依赖

主应用安装

npm i qiankun -S

3.给每个项目加入不同端口号

qiankun搭建_第2张图片

4.启动项目

三个都要启动
qiankun搭建_第3张图片

5.在主应用注册微应用

在入口文件index.js中配置需要的信息

import { registerMicroApps, start } from 'qiankun';

registerMicroApps([
  {
    name: 'react app',
    entry: '//localhost:3011',//端口号
    container: '#micro-app1',//挂载点
    activeRule: '/micro-app1',//路由
  },
  {
    name: 'vue app',
    entry: '//localhost:3012',
    container: '#micro-app2',
    activeRule: '/micro-app2',
  },
]);

start();

qiankun搭建_第4张图片

在qiankun-base\src\App.js编写挂载点

import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <div id="micro-app1"></div>
      <div id="micro-app2"></div>
    </div>
  );
}

export default App;

qiankun搭建_第5张图片

6.微应用导出生命周期,使主应用能够加载

两个微应用项目在 src 目录新增 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  /* global __webpack_public_path__:writable */
    __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
  }

两个微应用中qiankun-micro-app1\src\index.js修改如下生命周期:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import './public-path'

function render(props) {
  const { container } = props;
  ReactDOM.render(<App />, container ? container.querySelector('#root') : document.querySelector('#root'));
}

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) {
  const { container } = props;
  ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}

// 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();

7.修改webpack配置信息

功能:可以重写webpack配置信息
微应用都安装如下:

npm i react-app-rewired

然后都修改package.json
qiankun搭建_第6张图片

根目录创建config-overrides.js

qiankun搭建_第7张图片

填入:

const { name } = require('./package');

module.exports = {
  webpack: (config) => {
    config.output.library = `${name}-[name]`;
    config.output.libraryTarget = 'umd';//采用umd方式注入
    config.output.chunkLoadingGlobal = `webpackJsonp_${name}`;//webpack5要把 jsonpFunction,改为 chunkLoadingGlobal
    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;
  },
};

再次全部启动
qiankun搭建_第8张图片

8.查看效果

qiankun搭建_第9张图片

9.主应用与子应用的通信

主应用 qiankun-base\src\index.js

qiankun搭建_第10张图片

微应用的mount中可以接收

qiankun搭建_第11张图片

10.initGlobalState

主要是测试练手,不是一定要写

主应用qiankun-base\src\index.js加入如下代码

import {
  initGlobalState,
  registerMicroApps,
  start
} from 'qiankun';

const state = {
  nickname:'主应用山竹'
}

// 初始化state
const actions = initGlobalState(state)
actions.onGlobalStateChange((state, prev) => {
  // state:变更后的状态;prev变更前的状态
  console.log(state,prev,'主应用')
})
 setTimeout(() => {
  actions.setGlobalState({
    ...state,
    age: 19
  })
}, 2000)
actions.offGlobalStateChange()

微应用qiankun-micro-app1\src\index.js修改mount做接收

export async function mount(props) {
  console.log('[react16] props from main framework', props);
  props.onGlobalStateChange((state,prev)=>{
    // state:变更后的状态;prev变更前的状态
    console.log(state,prev,'微应用')
    setTimeout(() => {
      props.setGlobalState({
        ...state,
        age: 20
      })
    }, 2000)
  })
  render(props);
}

qiankun搭建_第12张图片

11.使用vue3做微应用

1.创建微应用

npm create qiankun-micro-vue3-app3

2.安装依赖

npm i qiankun -S

3.在如上public-path文件拷贝在src,引入到mainjs

qiankun搭建_第13张图片
4. 编写mainjs

import {
    createApp
} from 'vue'
import App from './App.vue'
import './public-path'

// createApp(App).mount('#app')

let instance = null

function render(props = {}) {
    console.log(props);
    const {
        container
    } = props
    instance = createApp(App);
    instance.mount(container ? container.querySelector('#app') : '#app')
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
    render();
}

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);
    instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange;
  instance.config.globalProperties.$setGlobalState = props.setGlobalState;
}

export async function unmount() {
    instance.unmount();
    instance.container.innerHTML = '';
    instance = null;
  }

qiankun搭建_第14张图片

qiankun搭建_第15张图片

12.react子应用接入路由

初始路由

npm install react-router-dom@6

修改主应用index.js页面

import { BrowserRouter } from 'react-router-dom'
root.render( 
<React.StrictMode >
  <BrowserRouter>
    <App / >
  </BrowserRouter>
  </React.StrictMode>
);

修改微应用index.js,注意不同微应用basename的名字

function render(props) {
  const { container } = props;
  ReactDOM.render(
    <BrowserRouter basename={window.__POWERED_BY_QIANKUN__?'/micro-app1':'/'}>
      <App />
    </BrowserRouter>
  , container ? container.querySelector('#root') : document.querySelector('#root'));
}

主应用qiankun-base\src\App.js


import { Link } from 'react-router-dom'
function App() {
  return (
    <div className="App">
      <Link to={"/micro-app1"}>micro-app1</Link>
      <Link to={"/micro-app2"}>micro-app2</Link>
      <div id="micro-app1"></div>
      <div id="micro-app2"></div>
      <div id="micro-app3"></div>
    </div>
  );
}

效果已经可以自由切换了
qiankun搭建_第16张图片

试试创建页面

qiankun-micro-app1\src\pages\Cat\index.js

import React from 'react'

export default function Cat() {
  return (
    <div>Cat</div>
  )
}

qiankun-micro-app1\src\pages\Dog\index.js

import React from 'react'

export default function Dog() {
  return (
    <div>Dog</div>
  )
}

qiankun-micro-app1\src\App.js

import logo from './logo.svg';
import './App.css';
import { Routes,Route,Link} from 'react-router-dom'
import Cat from './pages/Cat/index'
import Dog from './pages/Dog/index'

function App() {
  return (
    <div className="App">
      微应用1
      <Link to={"/cat"}>cat</Link> |
      <Link to={"/dog"}>dog</Link>
      <Routes>
        <Route path="/cat" element={<Cat/>}/>
        <Route path="/dog" element={<Dog/>}/>
      </Routes>
    </div>
  );
}

export default App;

效果

qiankun搭建_第17张图片

13.vue3子应用接入路由

初始路由

npm install vue-router

qiankun-micro-vue3-app3\src\router\index.js

import { createRouter, createWebHashHistory } from "vue-router";
import ZoonCat from "../view/ZoonCat.vue"
import ZoonDog from "../view/ZoonDog.vue"
const routes = [
    {
        path:'/ZoonCat',
        component:ZoonCat
    },
    {
        path:'/ZoonDog',
        component:ZoonDog
    },
]

const router = createRouter({
    history: createWebHashHistory(
        window.__POWERED_BY_QIANKUN__?'/micro-app3':'/'
    ),
    routes
})

export default router

随便来两个组件

qiankun搭建_第18张图片
qiankun-micro-vue3-app3\src\App.vue

<template>
  <div>
    <router-link to="/zoonCat">zoonCat</router-link>|
    <router-link to="/zoonDog">zoonDog</router-link>
    <router-view />
  </div>
</template>

qiankun-micro-vue3-app3\src\main.js


import router from './router/index'
//。。。其他代码
function render(props = {}) {
    console.log(props);
    const {
        container
    } = props
    instance = createApp(App);
    instance.use(router)
    instance.mount(container ? container.querySelector('#app') : '#app')
}

效果

qiankun搭建_第19张图片

以vue为主应用

1.创建项目

vue2为基底

vue create vue-base
vue create app1
vue create app2

2.安装路由

全部项目都要的

 npm install vue-router@3.2.0 -S

\src\router\index.js

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

import ZoonCat from "../view/ZoonCat.vue"
import ZoonDog from "../view/ZoonDog.vue"
const routes = [
    {
        path:'/ZoonCat',
        component:ZoonCat
    },
    {
        path:'/ZoonDog',
        component:ZoonDog
    },
]
const router = new VueRouter({
    mode: 'history',
    base:window.__POWERED_BY_QIANKUN__?'app-1':'/',
    routes,
  })
  

export default router

\src\main.js(暂时这么写着)

//其他代码
import router from './router/index'

 new Vue({
    router,
    // store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');

App.vue中映射

    <router-view/>

3.安装qiankun依赖

主应用安装

npm i qiankun -S

主应用注册微应用vue-base\src\main.js

import Vue from 'vue'
import App from './App.vue'
import { registerMicroApps, start } from 'qiankun';

Vue.config.productionTip = false
registerMicroApps([
  {
    name: 'app1',
    entry: '//localhost:81',
    container: '#app1',//挂载点
    activeRule: '/app-1',
  },
  {
    name: 'app2',
    entry: '//localhost:82',
    container: '#app2',
    activeRule: '/app-2',
  },
]);
// 启动 qiankun
start();

new Vue({
  render: h => h(App),
}).$mount('#app')

微应用\src\main.js配置生命周期之类的


import './public-path'
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'

Vue.config.productionTip = false

let instance = null;
function render(props = {}) {
  const { container } = props;

  instance = new Vue({
    router,
    //store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

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() {
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
}


主应用App.vue

<template>
  <div id="app">
    <router-link to="/app-1/ZoonCat">app1的猫</router-link>
    <br/>
    <router-link to="/app-1/ZoonDog">app1的狗</router-link>
    <br/>
    <router-link to="/app-2/ZoonCat">app2的猫</router-link>
    <br/>
    <router-link to="/app-2/ZoonDog">app2的狗</router-link>
    <div id="app1"></div>
    <div id="app2"></div>
    <router-view/>
  </div>
</template>

4.微应用src 目录新增 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

引入mainjs

import './public-path'

如果报 error ‘webpack_public_path’ is defined but never used no-unused-vars 的错误,在app1\package.json找到eslintConfig,输入以下代码,然后重启服务

 "eslintConfig": {
 //其他代码
    "globals": {
      "__webpack_public_path__": true
    }

  },

5.修改微应用vue.config.js

const { name } = require('./package');
module.exports = {
  devServer: {
    port: 82,//端口号
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      // jsonpFunction: `webpackJsonp_${name}`,webpack5可以不要
    },
  },
};

尝试下效果
qiankun搭建_第20张图片

6.接入vuex(传值通信,可以不学,自己看文档)

每个项目都要

npm install vuex@3

store\index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        username: ''
    },
    mutations: {
        changeName(state, username) {
            state.username = username
        }
    },
    actions: {
        changeName(context, username) {
            context.commit('changeName', username)
        }
    },
    modules: {}
})

main.js引入store

//其他代码
import store from './store'

new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');

主应用main.js

import { initGlobalState } from 'qiankun';

const state = {
  username: "山竹"
}
// 初始化 state
const actions = initGlobalState(state);
actions.onGlobalStateChange((state, prev) => {
  // state: 变更后的状态; prev 变更前的状态
  console.log(state, prev);
});
actions.setGlobalState(state);
actions.offGlobalStateChange();

store.dispatch('changeName',state.username),//这里只是通信例子,非必写

src\App.vue

{{$store.state}}

效果

qiankun搭建_第21张图片

子应用app1\src\main.js

//。。。其他代码
function storeTest(props) {
  props.onGlobalStateChange &&
    props.onGlobalStateChange(
      (value) => store.dispatch('changeName',value.username),
      true
    )
  props.setGlobalState &&
    props.setGlobalState({
      igone: props.name,
      user: {
        name: props.name
      }
    })
}

export async function mount(props) {
  console.log('[vue] props from main framework', props);
  storeTest(props)
  render(props);
}

效果
qiankun搭建_第22张图片

你可能感兴趣的:(javascript,react.js,前端,vue.js)