Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating pure web component from react components

i am trying to build web components from react components, it is all working fine, but there are two problems i am trying to solve:

  1. Is there a way to convert such web components to pure web component (using webpack, transpile or some other way), so that react and other dependencies are not bundled?
  2. Is there a way to just include the required portion of dependencies or it is all/none only, and have to use external setting of webpack to use host's version?

thanks

like image 254
syed Avatar asked Oct 15 '22 21:10

syed


1 Answers

For the first question, there is no direct way to convert React component into a Web Component. You will have to wrap it into a Web Component Class:

export function MyReactComponent() {
  return (
    <div>
      Hello world
    </div>
  );
}


class MyWebComponent extends HTMLElement {
  
  constructor() {
    super();
    // Do something more
  }

  connectedCallback() {
    
    // Create a ShadowDOM
    const root = this.attachShadow({ mode: 'open' });

    // Create a mount element
    const mountPoint = document.createElement('div');
    
    root.appendChild(mountPoint);

    // You can directly use shadow root as a mount point
    ReactDOM.render(<MyReactComponent />, mountPoint);
  }
}

customElements.define('my-web-component', MyWebComponent);

Of course, you can generalize this and create a reusable function as:

function register(MyReactComponent, name) {
  const WebComponent = class extends HTMLElement {
    constructor() {
      super();
      // Do something more
    }
  
    connectedCallback() {
      
      // Create a ShadowDOM
      const root = this.attachShadow({ mode: 'open' });
  
      // Create a mount element
      const mountPoint = document.createElement('div');
      
      root.appendChild(mountPoint);
  
      // You can directly use shadow root as a mount point
      ReactDOM.render(<MyReactComponent />, mountPoint);
    }
  }
  
  customElements.define(name, MyWebComponent);
}

register(MyReactComponent, 'my-web-component');

Same register function can be now re-used across all the components that you want to expose as web components. Further, if your component accepts props that should be passed, then this function can be changed to accept third argument as array of string where each value would be registered as a setter for this component using Object.define. Each time a setter is called, you can simply call ReactDOM.render again.

Now for the second question, there are multiple scenarios with what you are trying to do.

  • If you are bundling application and loading dependencies like React or others using CDN, then Webpack externals is a way to go. Here you will teach Webpack how to replace import or require from the global environment where app will run.
  • If you are bundling a library which you intend to publish to NPM registry for others to use in their applications, then you must build your project using library target configuration. Read more about authoring libraries here.

Bundling for libraries is slightly trickier as you will have to decide what will be your output format (common.js, ES Modules or UMD or Global or multiple formats). The ideal format is ES Module if you are bundling for browser as it allows better tree shaking. Webpack previously did not support Module format and has recently started supporting it. In general, I recommend Webpack for applications and Rollup.js for libraries.

like image 175
Harshal Patil Avatar answered Oct 18 '22 14:10

Harshal Patil