【问题标题】:creating pure web component from react components从反应组件创建纯 Web 组件
【发布时间】:2021-04-06 14:42:50
【问题描述】:

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

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

谢谢

【问题讨论】:

    标签: reactjs web-component


    【解决方案1】:

    对于第一个问题,没有直接的方法可以将 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);
    

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

    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');
    

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

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

    • 如果您正在捆绑 应用程序 并加载 React 或其他使用 CDN 的依赖项,那么 Webpack externals 是一种方法。在这里,您将教 Webpack 如何从应用运行的全局环境中替换 importrequire
    • 如果您要捆绑一个,您打算将其发布到 NPM 注册表以供其他人在他们的应用程序中使用,那么您必须使用 library target configuration 构建您的项目。阅读有关authoring libraries here 的更多信息。

    库的捆绑有点棘手,因为您必须决定输出格式是什么(common.js、ES 模块或 UMD 或全局或多种格式)。如果您为浏览器捆绑,理想的格式是 ES 模块,因为它可以更好地摇树。 Webpack 以前不支持 Module 格式,最近开始支持它。一般来说,我推荐 Webpack 用于应用程序,而 Rollup.js 用于库。

    【讨论】:

    • 感谢 Harshal 的回答。 webpack externals 是我们一直在考虑的方式。所以总的来说,现在似乎没有 util/package 可以将包装的 react 组件转换为纯 web 组件?
    【解决方案2】:

    React 不是用于构建原生 Web 组件的库。

    手工编写 web 组件也不是最好的选择,因为它不能处理条件、循环、状态更改、虚拟 dom 和其他开箱即用的基本功能。

    React、Vue Svelte 和其他自定义库当然有一些优点,而原生 Web 组件具有许多其他优势,例如生态系统简单性以及被浏览器和 W3C 移植。

    一些库可以帮助您以现代且方便的方式编写本机 Web 组件:

    • Lego 是轻量级、原生且功能齐全的 Vue 风格。
    • Nativeweb 轻量级原始网络组件
    • ElemX 概念验证,将原生 Web 组件绑定到 ElemX 功能。

    如果你真的想将 React 组件包装到原生 Web 组件中,你可以这样做:

    class MyComponent extends HTMLElement {
      constructor() {
        this.innerHTML = '<MyReactComponent />'
      }
    }
    
    customElements.define('my-component', MyComponent)
    

    并在您的 HTML 页面中使用它&lt;my-component /&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-09
      • 2019-05-30
      • 2021-12-20
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 2022-11-01
      相关资源
      最近更新 更多