从 React 组件创建纯 Web 组件

sye*_*yed 10 web-component reactjs

我正在尝试从 React 组件构建 Web 组件,一切正常,但有两个问题我正在尝试解决:

  1. 有没有办法将此类 Web 组件转换为纯 Web 组件(使用 webpack、transpile 或其他方式),以便 React 和其他依赖项不被捆绑?
  2. 有没有办法只包含依赖项的必需部分,或者仅包含全部/无,并且必须使用 webpack 的外部设置来使用主机的版本?

谢谢

Har*_*til 12

对于第一个问题,没有直接的方法将React组件转换为Web组件。您必须将其包装到Web 组件类中:

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);
Run Code Online (Sandbox Code Playgroud)

当然,您可以将其概括并创建一个可重用的函数,如下所示:

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');
Run Code Online (Sandbox Code Playgroud)

现在可以在您想要公开为 Web 组件的所有组件中重复使用相同的注册函数。此外,如果您的组件接受应传递的 props,则可以更改此函数以接受第三个参数作为字符串数组,其中每个值将使用 注册为此组件的 setter Object.define。每次调用 setter 时,您只需ReactDOM.render再次调用即可。

现在对于第二个问题,您想要做的事情有多种情况。

  • 如果您正在捆绑应用程序并加载像 React 或其他使用 CDN 的依赖项,那么 Webpack externals是一种不错的选择。在这里,您将教 Webpack 如何替换importrequire从应用程序运行的全局环境中进行替换。
  • 如果您要捆绑一个,并打算将其发布到 NPM 注册表以供其他人在其应用程序中使用,那么您必须使用库目标配置来构建您的项目。在此处阅读有关创作库的更多信息。

库的捆绑稍微复杂一些,因为您必须决定输出格式(common.js、ES 模块或 UMD 或全局或多种格式)。如果您要捆绑浏览器,则理想的格式是 ES 模块,因为它可以更好地进行树形抖动。Webpack 之前不支持 Module 格式,最近开始支持。一般来说,我推荐用于应用程序的 Webpack 和用于库的 Rollup.js。


小智 5

如果您想手动执行此操作,Harshal Patil 的答案就是您的最佳选择。我还想指出我帮助创建的一个库,react-to-webcomponent。它简化了这个过程并无缝支持 React 16-18。