micro-app icon indicating copy to clipboard operation
micro-app copied to clipboard

How to render same micro app twice on the same page?

Open Relaxe111 opened this issue 3 years ago • 9 comments
trafficstars

How i can render same app twice on the same page? image I ve managed to figure out how to pass data from main app to child app in order to tell on which path to render But second component not renders and I get following error: image my code in the main app:

microApp.start({

  plugins: {
    modules: {
      react1: [{
        loader(code: string) {
          //if (process.env.NODE_ENV === 'development') {
            code = code.replace(/(from|import)(\s*['"])(\/app-react1\/)/g, (all) => {
              
              return all.replace('/app-react1/', 'http://localhost:7002/app-react1/')
            })
         // }
          return code
        }
      }],
      react2: [{
        loader(code: string) {
          //if (process.env.NODE_ENV === 'development') {
            code = code.replace(/(from|import)(\s*['"])(\/app-react1\/)/g, (all) => {
              
              return all.replace('/app-react1/', 'http://localhost:7002/app-react1/')
            })
         // }
          return code
        }
      }]
    }
  },
  /**
   * 自定义fetch
   * @param url 静态资源地址
   * @param options fetch请求配置项
   * @returns Promise<string>
   */
  async fetch(url, options, _appName) {
    if (url === 'http://localhost:3001/error.js') {
      return Promise.resolve('')
    }

    let config = null
    if (url === 'http://localhost:3001/micro-app/react16/') {
      config = {
        headers: {
          'custom-head': 'custom-head',
        }
      }
    }

    const res = await fetch(url, Object.assign(options, config));
    return await res.text();
  }
})

and declaring in component:

<template>
  <div class="vite">
    <micro-app
      name='react1'
      url='http://localhost:7002/app-react1/'
      inline
    >
    <!-- destroy inline scopecss='false' -->
    </micro-app>
  </div>
  <div class="vite">
    +++++
    <micro-app
      name='react2'
      url='http://localhost:7002/app-react1/'
      inline
    >
    <!-- destroy inline scopecss='false' -->
    </micro-app>
  </div>
</template>

<script lang="ts">
import microApp, { EventCenterForMicroApp } from '@micro-zoe/micro-app';
  //@ts-ignore
  window.eventCenterForReact1 = new EventCenterForMicroApp('react1')
  //@ts-ignore
  window.eventCenterForReact2 = new EventCenterForMicroApp('react2')
  microApp.setData('react1',{component_path:'/user-select'})
  microApp.setData('react2',{component_path:'/selected-user-widget'})

</script>

<style>

</style>


in the child app i get both paths as it should.

What i am doing wrong? Thankyou.

Relaxe111 avatar Sep 05 '22 20:09 Relaxe111

micro app is vite?

bailicangdu avatar Sep 06 '22 03:09 bailicangdu

yes

Relaxe111 avatar Sep 06 '22 05:09 Relaxe111

vite doesn't support yet

bailicangdu avatar Sep 06 '22 05:09 bailicangdu

is there any workaround?

Relaxe111 avatar Sep 06 '22 06:09 Relaxe111

No, we're working on it

bailicangdu avatar Sep 06 '22 06:09 bailicangdu

Maybe i can contribute with something? I am not an expert in mfe. but if I could get some documentations and some details what/where to search i can make a try

Relaxe111 avatar Sep 06 '22 13:09 Relaxe111

Update: I think i found kind of workaround problem is that sometime it shows only first component, and i cant understand why? data always is coming as it should. ok: image renders only first instance of the app: image

what i do: First i declare as normal two with different names but same url after i main app i declare two times EventCenterForMicroApp for each of the app like :

// TwiceFromSameMicroAppWithDiferentComponents.vue
<template>
  <div class="vite">
    <micro-app
      name='react1'
      url='http://localhost:7002/app-react1/'
      inline
    >
    <!-- destroy inline scopecss='false' -->
    </micro-app>
  </div>
  <div class="vite">
    +++++
    <micro-app
      name='react2'
      url='http://localhost:7002/app-react1/'
      inline
    >
    <!-- destroy inline scopecss='false' -->
    </micro-app>
  </div>
</template>

<script lang="ts">
import microApp, { EventCenterForMicroApp } from '@micro-zoe/micro-app';
  //@ts-ignore
  window.eventCenterForReact1 = new EventCenterForMicroApp('react1')
  //@ts-ignore
  window.eventCenterForReact2 = new EventCenterForMicroApp('react2')
  microApp.setData('react1',{component_path:'/user-select',__MICRO_APP_NAME__:'react1'})
  microApp.setData('react2',{component_path:'/selected-user-widget',__MICRO_APP_NAME__:'react2'})

</script>

<style>

</style>

and in micro app i do following:

// main.tsx
import React from 'react'
import ReactDOM, { Root } from 'react-dom/client'
import App from './App'
import './index.css'

let root: Root|undefined
let gdata:{component_path?:string,__MICRO_APP_NAME__:string} |undefined
export function mount ():void {
  if (!root) {
    root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
  }

  root.render(
    <React.StrictMode>
      <App name = {gdata?.__MICRO_APP_NAME__}/>
    </React.StrictMode>
  )
}
export function unmount ():void {
  root?.unmount()
}


  // @ts-ignore
  if (window.eventCenterForReact1) {
    // @ts-ignore
    window.eventCenterForReact1?.addDataListener((data:{component_path?:string,__MICRO_APP_NAME__:string}) => {
        
      gdata = data

      console.log('eventCenterForReact1', gdata)
      // 当基座下发跳转指令时进行跳转
      setGlobalMicroAppName()
      console.log('push')
      //@ts-ignore
      window.eventCenterForReact1 = undefined
    }, true)
    //@ts-ignore
  } else if(window.eventCenterForReact2) {
    //@ts-ignore
    window.eventCenterForReact2?.addDataListener((data:{component_path?:string,__MICRO_APP_NAME__:string}) => {
      
      gdata = data

      console.log('eventCenterForReact2', gdata)
      // 当基座下发跳转指令时进行跳转
      setGlobalMicroAppName()
      console.log('push')
    }, true)
  }else {
    mount()

  }

function setGlobalMicroAppName(){
  
  console.log('app name:',gdata?.__MICRO_APP_NAME__ )
  //@ts-ignore
  window[`micro-app-${gdata.__MICRO_APP_NAME__}`] = { mount, unmount }
}

Relaxe111 avatar Sep 06 '22 20:09 Relaxe111

if micro app is vite, we do not recommend using micro-app for the time being, it will cause a lot of problems, and this is exactly what we need to do

bailicangdu avatar Sep 07 '22 04:09 bailicangdu

do you have any issue tracker related vite integration?

Relaxe111 avatar Sep 07 '22 06:09 Relaxe111