微前端(qiankun)主應用共享React元件

快樂的開發者發表於2022-06-08

前言

最近需要重構一個老專案,定的方案用微前端去改造。主應用是老的專案,微應用是新的專案,由於重構時間比較緊張,子應用還需要使用父應用的一些元件。過程中遇到一些問題,記錄一下。

方案

我們知道qiankun,可以通過props通訊傳遞資料,把元件通過props傳遞過去不就行了。來開始改造我們的程式碼

主應用

匯入元件,通過props共享出去

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

// 匯入一些元件 
import Custom_Date from "@date/config";
import CompanyTitle from '@title/config';
import CustomSelect from '@select/config';
import UpdateTime from '@updateTime/config';

const shareComponent = {
    Custom_Date,
    CompanyTitle,
    CustomSelect,
    UpdateTime
}

registerMicroApps([
  {
    name: 'child-app', // 一級市場
    entry: '//localhost:7011',
    container: '#childApp',
    activeRule: '/page/appPM',
    props: {
      base: '/page/app-child/',
      ...shareComponent
    },
  },

]);

子應用

在qiankun的生命週期函式接收props,並快取。

快取元件工具函式

let shareMainComponent: Record<string, any> = {}

// 獲取共享的元件
export const getShareMainComponent = () => {
  return shareMainComponent;
}

// 設定共享的元件
export const setShareMainComponent = (currShareMainComponent: Record<string, any>) => {
  for (const key in currShareMainApp) {
    if (Object.prototype.hasOwnProperty.call(currShareMainComponent, key)) {
      shareMainComponent[key] = currShareMainComponent[key];
    }
  }
}

子應用生命週期中設定共享元件

import { setShareMainComponent } from './utils/shareMainComponent';
export const qiankun = {

  async bootstrap(props: any) {
    console.log('app1 bootstrap', props);
  },
  // 應用 render 之前觸發
  async mount(props: any) {
    setShareMainComponent(props.shareMainApp);
  },
  async unmount(props: any) {
    console.log('app1 unmount', props);
  },
};

子應用使用

import React, { FC, useEffect, useState } from 'react';
import { getShareMainComponent } from '../../../utils/shareMain';

export interface IndexConfigPageProps {
}

const IndexConfigPage: FC<IndexConfigPageProps> = props => {
    const {
      Custom_Date,
      CompanyTitle,
      CustomSelect,
      UpdateTime
    } = getShareMainComponent();

    useEffect(() => {
    }, []);


    return (
        <div>
            <Custom_Date />
            <CustomTitle />
        </div>
    );
}

export default IndexConfigPage;

hooks元件問題

類元件正常是沒問題的,但hooks元件會有問題,報錯如下

image.png
經排查分析,應該是React不是一個例項,hooks元件需要同一個例項。

解決方案

藉助webpack的externals去用同一份React。

主應用

主應用入口index.html引入react和react-dom的js檔案

<script src="<%= htmlWebpackPlugin.files.publicPath %>public/react/react.development.js"></script>
<script src="<%= htmlWebpackPlugin.files.publicPath %>public/react-dom/react-dom.development.js"></script>

配置webpack的externals,如下

externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
},

主應用設定完成,下面開始配置子應用。

子應用

子應用這時就不需要引入相關的js檔案,直接配置externals,用主應用的React和ReactDom。配置如下

  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM',
  },

在此訪問,問題得已解決

結束語

我們在重構巨石老專案的時候,可以考慮微前端,用微前端(qiankun)共享元件的時候,可以使用該方案。

如果你覺得該文章不錯,不妨

1、點贊,讓更多的人也能看到這篇內容

2、關注我,讓我們成為長期關係

3、關注公眾號「前端有話說」,裡面已有多篇原創文章,和開發工具,歡迎各位的關注,第一時間閱讀我的文章

相關文章