DEV Community

Cover image for Navigating Webpack Module Federation: Managing React 17 and React 18 Integration
jeancatarina
jeancatarina

Posted on

Navigating Webpack Module Federation: Managing React 17 and React 18 Integration

Today's fast-paced tech realm presents challenges with different React versions coexisting in one environment. This article explores integrating React 17 and React 18 within Webpack Module Federation, ensuring a seamless partnership.

The interaction between React 17 (father app) and React 18 (child app) faces inherent challenges due to their distinct virtualized DOMs. Rendering both together can spark version conflicts, demanding a thoughtful strategy for integration.

Setting Up the Father App (React 17)

In the father app, we face the challenge of incorporating a child app built with React 18 while maintaining isolation. To address this, we create a designated <div> within the father app where the React 18 child will render, avoiding conflicts with the React 17 DOM structure.

// Father App (React 17)
const componentCleanup = useCallback(() => {
  unmount()
}, [remotes.name])

useEffect(() => {
  mount({
    idParent: "children_app"
  })

  window.addEventListener('beforeunload', componentCleanup)

  return () => {
    componentCleanup()
    window.removeEventListener('beforeunload', componentCleanup)
  }
}, [componentCleanup])

<div id="children_app" />
Enter fullscreen mode Exit fullscreen mode

Child App (React 18) Integration

The child app, developed with React 18, employs a mount controller to handle the rendering process within the specified <div> of the father app. This ensures the creation of an isolated instance of React 18, mitigating version conflicts.

import { createRoot } from 'react-dom/client'

import App from './App/appMain/AppMain'

window.childapp_ready = false
const RootCache = new Map()

function handleRecoverableError(error) {
  console.error('CHILD-APP ERROR:', error)
}

function mount({ idParent }) {
  if (window.childapp_ready) return

  const container = document.getElementById(idParent)

  const root = createRoot(container, {
    onRecoverableError: handleRecoverableError
  })

  root.render(<App />)

  window.childapp_ready = true

  RootCache.set(idParent, root)

  return root
}

function unmount({ idParent }) {
  RootCache.get(idParent)?.unmount()
  window.childapp_ready = false
}

export default { mount, unmount }

Enter fullscreen mode Exit fullscreen mode

Webpack Configuration for Child App

The webpack configuration for the child app ensures proper sharing and handling of React versions within the Webpack Module Federation setup:

module.exports = {
  name: 'childapp',
  path: 'build-child',
  port: 3333,
  openBrowser: false,
  remotes: [],
  exposes: [
    {
      componentName: 'App',
      componentPath: './src/App/appMain/AppMain.tsx'
    },
    {
      componentName: 'Mount',
      componentPath: './src/mountApp.js'
    }
  ],
  shared: {
    react: {
      requiredVersion: '*',
      import: 'react',
      shareKey: 'react',
      shareScope: 'default',
      singleton: false
    },
    'react-dom': {
      requiredVersion: dependencies['react-dom'],
      singleton: true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Managing React 18 Isolation

By leveraging this structured approach, invoking the mount function within the father app ensures an encapsulated instance of React 18 is rendered within the designated <div>. This segregation prevents interference between the React 17 and React 18 instances, promoting a conflict-free environment.

Now we can see that we have two reacts working in the same page!
Image description

Closing Thoughts

Managing the integration of disparate React versions demands meticulous planning and implementation. Utilizing Webpack Module Federation provides a strategic avenue to ensure the coexistence of React 17 and React 18 without version conflicts.

example github project: https://github.com/module-federation/module-federation-examples/tree/master/different-react-versions-isolated

Feel free to connect with me on LinkedIn for further discussions and insights into React version integration using Webpack Module Federation.

Top comments (0)