Webpack中的同步require

6

我正在使用webpack,并使用require引入一些包。我有两个包:package1.js和package2.js。 package1.js只是创建一个带有一些属性的对象,称为pkg1。 package2是一个包含自执行函数的javascript文件,该函数扩展了package1。例如:

package2.js:

!function () {
    pkg1.prototype.newFunction = function {return "foo"};
}()

我正在尝试以以下方式将它们都要求到一个新脚本中:
require('package1')
require('package2')

当我这样做时,出现错误:
Uncaught TypeError: pkg1.newFunction is not a function

我认为这是由于JavaScript的异步加载引起的:require(package2)require('package1')之前执行。我的证据是,当我做以下操作时,我不会出现错误:

require('package1')
!function () {
    pkg1.prototype.newFunction = function {return "foo"};
}()

不过,这样很混乱,我想使用require。如何使其正常工作?

编辑:具体例子

leaflet-d3插件的开头是:

(function() {
    L.HexbinLayer = L.Class.extend({
    ...
 })()

因此,至少我理解的是,在代码中加入require(leaflet-d3-plugin)应该会导致该脚本执行并扩展L,而L是由require('leaflet')引入的。
同样地,d3-hexbin-v0的起始代码如下:
!function(){d3.hexbin=function(){
    ...
}}()

我理解的这段代码是,它将一个名为 .hexbin 的方法添加到 d3 库中。

但如果我只是写 HTML,我会将这些不同的内容放在各种脚本标记中,然后就可以正常使用:

<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/d3.hexbin.v0.min.js"></script>

或者
<script src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js"></script>
<script src="static/leaflet-d3.min.js" charset="utf-8"></script>

但由于我正在使用webpack,我应该能够在安装了它们之后,通过require和/或import这些库,或者如果我只是将这些脚本中的.js复制到某个目录中,然后从那个位置require他们。不幸的是,除非我直接将这些模块中的.js复制到我正在编写的脚本中,否则这似乎无法正常工作。这就是我想要避免的情况。
例如:
import * as d3 from 'd3'; \\I'm using d3 v4 here.
require('/resources/d3-hexbin.min.js')

结果为:

Uncaught TypeError: d3.hexbin is not a function

1
"package1.js 简单地创建了一个名为pkg1的带有一些属性的对象" 好的。 但是变量 pkg1 应该从哪里来? "我遇到了一个错误:Uncaught TypeError: pkg1.newFunction不是函数"这通常发生在您尝试调用不是函数的值时。 您在哪里尝试调用 pkg1.newFunction? 您的示例似乎相当不完整,这使得难以帮助您。 请阅读[mcve]。 - Felix Kling
require() 调用在浏览器中实际上从未被执行过。没有任何浏览器支持 require。Webpack 会构建一个“捆绑”了 JavaScript 代码的文件,使其能够在浏览器中兼容运行。更多阅读:http://blog.andrewray.me/webpack-when-to-use-and-why/ - Andy Ray
感谢@FelixKling的反馈。我不知道如何在不提供整个webpack项目的情况下使其可验证,而且我认为没有人想要经历这一过程。我已经通过一些具体的例子来扩展问题。希望它们有助于缩小范围。 - Logister
我写了@asymmetrik/leaflet-d3。在写的时候,我在为leaflet-d3设置基于模块的打包时出了问题,没有正确指定d3和d3.hexbin的依赖关系,这导致在像webpack这样的打包工具中使用leaflet-d3时出现问题。这意味着你需要费些周折才能正确地将d3.hexbin包注册到全局命名空间d3上,并使其可用于正确的模块。最新版本(1.4)应该解决了这个问题。您只需导入d3和d3-hexbin并在提供插件中配置d3即可。 - reblace
1个回答

4
Webpack同步加载文件,但每个文件都有自己的作用域。 这就是为什么在你的语句中。
import * as d3 from 'd3'; \\I'm using d3 v4 here.
require('/resources/d3-hexbin.min.js')

你的第二个问题是找不到d3变量。

你可以通过使用ProvidePlugin来解决它:

webpack.config.js

plugins: [
  new webpack.ProvidePlugin({
    d3: 'd3'
  }),
  ... //other plugins

这样d3就会在整个应用程序中可用。

另一种实现方式是使用以下方法:

import * as d3 from 'd3';
window.d3 = d3;
require('./d3.hexbin.v0.min.js')

希望能为您提供帮助!

这是所有正确的信息。问题中提到的特定问题与d3-hexbin未在leaflet-d3包范围内加载有关。这会导致“d3.hexbin不是函数”的错误。这个具体问题已经在@asymmetrik/leaflet-d3 v1.4中得到解决。现在,这个答案肯定可以工作。您只需要导入d3和d3-hexbin,然后配置提供插件即可。 - reblace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接