Search code examples
reactjsweb-component

Importing and running a standalone React application inside a web component


I have a standalone React application that uses webpack for bundling with a requirement of being able to run this bundle within a web component. Can anyone suggest how I should approach this?

I'm thinking something like:

//webpack.config.js
output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js',
        library: 'reactUmd',
        libraryTarget: 'umd',
        umdNamedDefine: true
    },

//react-component.js
import '../../packages/react-umd/dist/bundle.js'

class ReactComponent extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement('span');
    this.attachShadow({ mode: 'open' }).appendChild(mountPoint);
    reactUmd.renderSomeComponentTo(mountPoint)
  }
}

customElements.define('react-component', ReactComponent)

But I'm not sure how I can import the compiled bundle and get a reference to React, ReactDOM, the Main component etc, would exporting as UMD provide the references I need?


Solution

  • So you basically want to access the react component outside the minified bundle file.

    Here is one approach:

    • You tell webpack to create a library for your file. This will basically create a global variable using which you can access all the exported functions from you js entry file. To do so, add a key called library int your webpack config under output object.

      module.exports = { entry: './main.js', output: { library: 'someLibName' }, ... }

    • After doing this, restart your webpack server and on console, type window.someLibName. This should print all the methods exported by main.js as an object.

    • Next step is to create a function which accepts a DOM element and renders the react component on the element. The function would look something like this:

      export const renderSomeComponentTo = (mountNode) => { return ReactDOM.render(<App />,MOUNT_NODE); }

    • Now you can access the above function from anywhere in the project, using

      const mountNode = document.getElementById('theNodeID'); window.someLibName.renderSomeComponentTo(mountNode);

    This way, all the react specific code is abstracted :)

    I hope I answered your question. Don't forget to hit star and upvote. Cheers 🍻