如何从Webpack bundle中公开对象并将外部lib注入编译的bundle?

时间:2016-10-14 05:21:18

标签: reactjs webpack

短版

TL; DR我希望能够从Webpack包中公开任意对象和函数(我们称之为Bundle2),我可以在另一个(独立的和无关的)包(Bundle1)中使用它。

例如,Bundle2可能是一个React应用程序,充当Bundle1中的小部件。然后Bundle2会以某种方式公开React组件,actions和reducers,以便Bundle1可以使用它(比如组合reducers,渲染Bundle2组件等)。

但我也希望Bundle2使用已包含在Bundle1中的一些库来节省空间。

我知道我可以使用Webpack options.externals从包中排除libs,然后我就可以了。但它预计外部因素将成为全球对象。我希望能够以某种方式将Bundle1中的依赖项注入Bundle2,就像通过道具一样。我不想在Bundle1中设置window.React = require('react'),以便Bundle2可以使用React。

编辑:一个澄清点......我的用例是我希望用户能够从商店或类似的东西添加小部件。由于可能存在数以千计的小部件,我认为在编译时(即使使用Webpack的块或代码拆分功能)将所有这些小部件(可以是用户生成的)包含在主包中也不可扩展或可行。 。此外,我认为通过我的webpack运行其他人的代码是危险的,因为他们基本上可以通过这种方式运行任意本机代码。相反,我希望其他人的小部件驻留在我的服务器上,当他们“安装”时,我基本上将小部件代码异步加载到他们的仪表板中。

长版

假设我有以下Webpack包:

  • dashboard.bundle.js,主应用程序包。它是Redux的React应用程序。
  • clockWidget.bundle.js,它定义了一个时钟React组件,并使用Redux根据其状态更新自身。因此,它有一个根组件,一个reducer和一些动作。

在运行时,使用clockWidget.bundle.jsdashboard.bundle.js异步加载到require.js,有点像这样:

// Inside dashboard.bundle.js
requirejs(['clockWidget.bundle.js'], (widgetFunc) => {
  // I want to be able to do this:
  const widget = widgetFunc();
  const { actions, reducer, Component } = widget;

// Where:
// Component - is a React component I can render either server-side or client-side inside the dashboard bundle.
// actions & reducer - are Redux actions and reducers
});

基本上,clockWidget将被异步引入并使用dashboard捆绑包提供的ComponentclockWidget内的某处呈现。

为了减少clockWidget捆绑包的大小,我使用Webpack的options.externals功能从捆绑包中排除React,因为dashboard.bundle.js已经拥有它。

我希望能够做到这样的事情:

// inside dashboard.bundle.js:

import React from 'react';
//...
requirejs(['clockWidget.bundle.js'], (widgetFunc) => {
  // Give the clockWidget bundle access to React:
  const widget = widgetFunc({ React })();
  // Then calling that gives me all the stuff I need, like before:
  const { actions, reducer, Component } = widget;
  // ...rendering the component, etc...
});

但我无法弄清楚如何做到这一点。我尝试过这样的事情:

// Inside the compiled clockWidget.bundle.js:

// Wrap the Webpack output with a RequireJS define,
// and return an object with the actions, reducer, and component from inside the bundle.
define(() => {

  //  I can make Webpack generate this code using 
  // output: {
  //    libraryTarget: 'var'
  // }
  var bundle = function() {
    // imagine minified webpack code in here...
  };
  // ^ I want to somehow pass down instances to React and other libs
  // so this bundle can consume it. If I use webpack's options.externals,
  // I can simply expose libs globally in dashboard.bundle.js to do the trick, but that smells bad to me.

  // Expose these keys to RequireJS:
  return {
    Actions: {}, // somehow point Actions to the webpack compiled actions
    Reducer: {}, // point Reducer to the webpack compiled reducer
    Component: {}, // point Component to the webpack compiled component
  };
});

我将非常感谢您对我如何处理此问题的任何意见或见解。谢谢:))

0 个答案:

没有答案