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

前言

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

方案

我們知道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、關注公衆號「前端有話說」,裏面已有多篇原創文章,和開發工具,歡迎各位的關注,第一時間閱讀我的文章

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章