微前端 qiankun

首先,官網(wǎng)祭天保佑~

微前端特性:

  • 子應(yīng)用可自主選擇技術(shù)棧
  • 各應(yīng)用單獨(dú)部署舷丹、互不依賴

然后像鸡,開始整。

主應(yīng)用

  1. 創(chuàng)建微應(yīng)用容器
<!-- app.vue -->
<template>
  <div id="appBase">
    <el-menu :router="true" mode="horizontal">
      <!--主應(yīng)用內(nèi)容-->
      <el-menu-item index="/">Home</el-menu-item>
      <el-menu-item index="/about">About</el-menu-item>
      <!--子應(yīng)用內(nèi)容-->
      <el-menu-item index="/vue">vue應(yīng)用</el-menu-item>
      <el-menu-item index="/react">react應(yīng)用</el-menu-item>
    </el-menu>
    <router-view></router-view>
    <!-- 與 main.js 里面配置的 container 對應(yīng)-->
    <div id="vue"></div>
    <div id="react"></div>
  </div>
</template>

<script>

export default {
  name: 'appBase',
  components: {
  }
}
</script>
  1. 注冊微應(yīng)用

  2. 啟動 qiankun席爽;

import { registerMicroApps, start } from 'qiankun';

const apps = [
  {
    name: 'vueApp', // 應(yīng)用的名字
    entry: '//localhost:8081', // 默認(rèn)會加載這個html 解析里面的js 動態(tài)的執(zhí)行 (子應(yīng)用必須支持跨域)fetch
    container: '#vue', // 容器名(主應(yīng)用頁面中定義的容器id,用于把對應(yīng)的子應(yīng)用放到此容器中)
    activeRule: '/vue', // 激活的路徑
    props: { name: 'vueApp' }   // 傳遞的值(可選)
  },
  {
    name: 'reactApp',
    entry: '//localhost:3000',
    container: '#react',
    activeRule: '/react',
  }
]
registerMicroApps(apps); // 注冊應(yīng)用
start({
  prefetch: false // 取消預(yù)加載
});

當(dāng)微應(yīng)用信息注冊完之后,一旦瀏覽器的 url 發(fā)生變化卵惦,便會自動觸發(fā)qiankun 的匹配邏輯,所有 activeRule 規(guī)則匹配上的微應(yīng)用就會被插入到指定的 container 中瓦戚,同時依次調(diào)用微應(yīng)用暴露出的生命周期鉤子

子應(yīng)用

  1. 建議使用 history 模式的路由沮尿,需要設(shè)置路由 base,值和它的 activeRule 一樣,當(dāng)然也可以選擇hash畜疾,詳細(xì)區(qū)別見入門教程 - 路由模式如何選擇
  2. 在入口文件 main.js中動態(tài)添加運(yùn)行時的 publicPath赴邻,修改并導(dǎo)出三個生命周期函數(shù)。
    注:運(yùn)行時的 publicPath 和構(gòu)建時的 publicPath 不同啡捶。
  3. 修改 webpack 打包姥敛,允許開發(fā)環(huán)境跨域和 umd 打包。

vueApp

// main.js
import Vue from 'vue'
import VueRouter from "vue-router";
import App from './App.vue'
import routes from './routes'

Vue.use(VueRouter);
Vue.config.productionTip = false;

let instance = null;
let router = null;

/**
 * 渲染函數(shù)
 * 兩種情況:主應(yīng)用生命周期鉤子中運(yùn)行 / 微應(yīng)用單獨(dú)啟動時運(yùn)行
 */
function render(props) {
  // 在 render 中創(chuàng)建 VueRouter瞎暑,可以保證在卸載微應(yīng)用時彤敛,移除 location 事件監(jiān)聽,防止事件污染
  router = new VueRouter({
    // 運(yùn)行在主應(yīng)用中時了赌,添加路由命名空間 /vue
    base: window.__POWERED_BY_QIANKUN__ ? "/vue" : "/",
    mode: "history",
    routes,
  });

  const el = props?.containter || '#appVue'
  // 掛載應(yīng)用
  instance = new Vue({
    router,
    render: (h) => h(App),
  }).$mount(el);
}

if (window.__POWERED_BY_QIANKUN__) { // 動態(tài)添加publicPath
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
if (!window.__POWERED_BY_QIANKUN__) { // 默認(rèn)獨(dú)立運(yùn)行
  render();
}
// 父應(yīng)用加載子應(yīng)用墨榄,子應(yīng)用必須暴露三個接口:bootstrap、mount勿她、unmount
// 子組件的協(xié)議就ok了
export async function bootstrap(props) {
  console.log('bootstrap', props)
}

export async function mount(props) {
  render(props)
}

export async function unmount(props) {
  console.log('unmount', props)
  instance.$destroy();
  instance.$el.innerHTML = '';
  instance = null;
  router = null;
}

此處踩了好幾個坑渠概,最大坑是這行代碼:

 const el = props?.containter || '#appVue'
// 然后掛載

原因是子應(yīng)用加載不出頁面,并且 qiankun 拋出微應(yīng)用加載后容器 DOM 節(jié)點(diǎn)不存在了嫂拴,然后檢查元素發(fā)現(xiàn)該子應(yīng)用的 id是另一串:<div id="__qiankun_microapp_wrapper_for_vue_app__" data-name="vueApp" data-version="2.6.3">播揪,由此可推出是掛載時發(fā)生的報(bào)錯。最坑的是當(dāng)自己傻傻花了好久解決的報(bào)錯筒狠,在我事后查看官網(wǎng)時發(fā)現(xiàn)了常見問題中已經(jīng)給出了答案...
ps: 常常都是解決了問題才發(fā)現(xiàn)官網(wǎng)上有寫猪狈,只有我這樣的鐵憨憨才有這樣的苦惱嗎...

// vue.config.js
module.exports = {
  devServer: {
      port: 8081, //這里的端口是必須和主應(yīng)用配置的子應(yīng)用端口一致
      headers: {
          //因?yàn)閝iankun內(nèi)部請求都是fetch來請求資源,所以子應(yīng)用必須允許跨域
          'Access-Control-Allow-Origin': '*'
      }
  },
  configureWebpack: {
      output: {
          //資源打包路徑
          library: 'vueApp',
          libraryTarget: 'umd'
      }
  }
}

reactApp

  • index.js文件
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

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

if (window.__POWERED_BY_QIANKUN__) {
  console.log('QIANKUN', window['reactApp'])
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

if(!window.__POWERED_BY_QIANKUN__){
  console.log('N_QIANKUN')
  render();
}

export async function bootstrap(){
 
}
export async function mount(props) {
  console.log('mount', props)
  render(props)
}
export async function unmount(props) {
  const container = props?.container;
  ReactDOM.unmountComponentAtNode(container ? container.querySelector('#root') : document.querySelector('#root'));
}
  • 修改 webpack 配置
    官網(wǎng)例子中安裝插件 @rescripts/cli辩恼,還可以選擇其他的插件雇庙,于是這里安裝的是react-app-rewired
npm install react-app-rewired
// 修改package.json
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test",
+   "test": "react-app-rewired test",
-   "eject": "react-scripts eject"
+   "eject": "react-app-rewired eject",
  • 創(chuàng)建打包配置config-overrides.js
module.exports = {
  webpack: (config) => {
      config.output.library = 'reactApp';
      config.output.libraryTarget = 'umd';
      config.output.publicPath = 'http://localhost:3000/';  // 此應(yīng)用自己的端口號
      return config;
  },
  devServer: (configFunction) => {
      return function (proxy, allowedHost) {
          const config = configFunction(proxy, allowedHost);
          config.headers = {
              "Access-Control-Allow-Origin": '*'
          }
          return config
      }
  }
}

react 的相關(guān)配置還算順利

代碼:demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灶伊,隨后出現(xiàn)的幾起案子疆前,更是在濱河造成了極大的恐慌,老刑警劉巖聘萨,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竹椒,死亡現(xiàn)場離奇詭異,居然都是意外死亡米辐,警方通過查閱死者的電腦和手機(jī)胸完,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來翘贮,“玉大人赊窥,你說我怎么就攤上這事±暌常” “怎么了锨能?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我址遇,道長熄阻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任傲隶,我火速辦了婚禮饺律,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘跺株。我一直安慰自己复濒,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布乒省。 她就那樣靜靜地躺著巧颈,像睡著了一般。 火紅的嫁衣襯著肌膚如雪袖扛。 梳的紋絲不亂的頭發(fā)上砸泛,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天,我揣著相機(jī)與錄音蛆封,去河邊找鬼唇礁。 笑死,一個胖子當(dāng)著我的面吹牛惨篱,可吹牛的內(nèi)容都是我干的盏筐。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼砸讳,長吁一口氣:“原來是場噩夢啊……” “哼琢融!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起簿寂,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤漾抬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后常遂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纳令,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年烈钞,在試婚紗的時候發(fā)現(xiàn)自己被綠了泊碑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡毯欣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出臭脓,到底是詐尸還是另有隱情酗钞,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站砚作,受9級特大地震影響窘奏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葫录,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一着裹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧米同,春花似錦骇扇、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熬苍,卻和暖如春稍走,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柴底。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工婿脸, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柄驻。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓狐树,卻偏偏與公主長得像,于是被迫代替她去往敵國和親凿歼。 傳聞我的和親對象是個殘疾皇子褪迟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容