动态加载React组件

big*_*ind 8 javascript reactjs webpack

我正在考虑构建一个Web应用程序,人们可以在其中安装插件.我希望插件能够定义将呈现给页面的React组件,而无需在安装插件后重新编译主JavaScript包.

所以这就是我想到的方法:

  • 使用webpack 将主要的JavaScript与React捆绑为外部库.
  • 插件作者也使用React将其组件编译为外部库.

这样,我只运行一个React实例.我可能会对其他一些常用的库做同样的事情.

那么问题是如何从服务器动态加载这些插件组件.假设我有以下组件:

class PluginRenderer extends React.Component{
  componentWillMount() {
    getPluginComponent(`/plugins/${this.props.plugin}/component.js`).then((com) => {
      this.setState({pluginComponent: com});
    })
  }

  render() {
    var Plugin = this.state.pluginComponent;
    return Plugin ? <Plugin {...this.props} /> : "Loading..."
  }
}
Run Code Online (Sandbox Code Playgroud)

怎么可以getPluginComponent实现?

Cha*_*own 7

这是一个有趣的问题,几个月前我也面临过客户工作,我没有看到太多的文档方法.我们做的是:

  1. 单个插件将是单独的Webpack项目,我们为其提供生成项目模板的模板或CLI工具.

  2. 在这个项目中,我们externals为已经在核心应用程序中使用的共享供应商库定义了Webpack :React,Redux等.这告诉插件不要包含那些包中的那些,而是从window我们在核心应用程序中设置的变量中获取它们.我知道,听起来很糟糕,但它比让所有插件重新包含1000个共享模块要好得多.

  3. 重用这个概念external,核心应用程序还通过窗口对象提供一些服务到插件.最重要的一个是PluginService.register()插件在初始化时必须调用的方法.我们在这里反向控制:插件有责任说"嗨,我在这里,这是我的主要导出(组件,如果它是一个UI插件)"到核心应用程序.

  4. 核心应用程序有一个PluginCache类/模块,它只是为加载的插件保存一个缓存(pluginId - >无论插件导出,fn,类等等).如果某些代码需要一个插件来呈现,它会向此缓存请求它.这样做的好处是允许在插件未正确加载时返回一个<Loading /><Error />组件,等等.

  5. 对于插件加载,这个PluginService/Manager加载插件配置(我应该加载哪些插件?)然后创建动态注入的script标签来加载每个插件包.捆绑完成后,将register调用步骤3中描述的调用,并且步骤4中的缓存将具有该组件.

  6. 而不是尝试直接从组件加载插件,而是从缓存中请求它.

这是一个非常高级别的概述,它与我们的要求非常相关(它是一个类似仪表板的应用程序,用户可以动态添加/删除面板,所有这些小部件都作为插件实现).

根据你的情况,你甚至可以使用<Provider store={ theCoreStore }> 包装插件,这样他们就必须访问Redux,或者设置某种类型的事件总线,以便插件可以相互交互......有很多东西可以提前搞清楚.:)

祝你好运,希望它以某种方式帮助!