无法理解webpack如何捆绑依赖项

时间:2016-06-07 07:45:35

标签: typescript three.js webpack

我很难理解webpack如何在一个包中包含依赖项。

我使用webpack,typescript和threejs构建了一个最小化的演示,工作正常。 It's on github here

第一个问题是我不明白如何在bundle.js中包含三个jj。它认为它确实很棒!我只是不明白它是如何被包含的。

第二个问题出现在我尝试添加另一个包(npm install --save three.trackball)时。我为它添加了typings

typings install --save --global dt~three-trackballcontrols

它编译正常,但在浏览器中加载失败时出现此错误:

THREE.TrackballControls is not a constructor

我明白为什么这样做:轨迹球JS文件不在HTML中。但我无法弄清楚如何在那里得到它,部分是因为我无法弄清楚three依赖关系是如何进入那里的!

轨迹球WIP在上面的回购中作为分支WIP-trackball

5 个答案:

答案 0 :(得分:2)

我正在使用angular-cli来编写一个angular2 / typescript项目。 Angular-cli现在使用webpack,但webpack配置不会暴露。

我在使用Three.js TrackballControls时遇到了类似的问题。我终于通过将相应的包添加到我的package.json

来得到了一些工作
"dependencies": {
  "@angular/common": "^2.4.0",
  "@angular/compiler": "^2.4.0",
  "@angular/core": "^2.4.0",
  "@angular/forms": "^2.4.0",
  "@angular/http": "^2.4.0",
  "@angular/platform-browser": "^2.4.0",
  "@angular/platform-browser-dynamic": "^2.4.0",
  "@angular/router": "^3.4.0",
  "@types/three": "^0.83.3",
  "core-js": "^2.4.1",
  "rxjs": "^5.0.1",
  "three": "^0.84.0",
  "three-trackballcontrols": "^0.0.5",
  "ts-helpers": "^1.1.1",
  "zone.js": "^0.7.2"
},

three的@types包含TrackballControls类型,但js未包含在three模块中。

我仍然在努力解决的问题是为什么我无法在我的ts中使用import语句进行三轨控制

import TrackballControls from 'three-trackballcontrols'

导致"无法精确模块和三轨球控制'"

我求助于

//import TrackballControls from 'three-trackballcontrols'
var TrackballControls = require('three-trackballcontrols');

this.controls = new TrackballControls(this.camera, this.container);

在我的打字稿类中。

我相信Andrew E的优秀答案,他正在为ThreeJS混合两种不同的轨迹球实现。

three.trackball:"将three.js轨迹球控制改编为commonjs模块"是一个与three-trackballcontrols不同的实现:"一个模块,用于在nodejs"中使用THREE.TrackballControls。我相信三轨球控制是来自ThreeJS存储库的实现,并匹配three模块中的输入。虽然接口目前是相同的,但我认为没有明确可用于three.trackball的打字。

答案 1 :(得分:0)

这是一个部分答案和解决方法,而不是一个适当的"回答。希望它能帮助别人。

TL; DR:

webpack.config.js声明THREE作为外部模块:

externals: {
  three: 'THREE'
},

这会阻止THREE加入bundle.js,这有利有弊。总的来说,这是一场胜利。

HTML结束:

...
<script src="http://threejs.org/build/three.min.js"></script>
<script src="http://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="bundle.js"></script>
</body>
</html>

请注意&#34;外部&#34;并不意味着&#34;必须来自第三方网站&#34;。它只是意味着&#34;不包含在bundle.js&#34;。

更长的解释

我一直试图解决太多事情。我想出这样的事情:

&#34; WebPack能够获取所有依赖项,包括THREE和轨迹球以及其他三个实用程序模块, 他们使用typings信息,打包,缩小并将它们捆绑到一个bundle.js 文件 - 也可以做很多事情&#34;

这是真的,但不是继续前进的有效方法。

相反,我认为WebPack可以很好地打包应用程序代码,尽管可以打包供应商代码, 它为有限的利益开辟了太多奇怪的问题 - 所以将这些依赖关系保持在外部。

尝试在THREE中同时包含bundle.js和轨迹球控件是非常有问题的。 包括THREE本身很简单并且第一次工作,但我无法做到 弄清楚轨迹球或轨道控制为何如此成问题。

存在多个问题。

一个是dt输入信息的名称不正确:

$ ls -C1 typings/globals/
three
three-orbitcontrols
three-trackballcontrols

这些名称很好且合乎逻辑 - 但NPM模块不同:

$ grep -i three package.json
"three": "^0.77.1",
"three-orbit-controls": "^72.0.0",
"three.trackball": "0.0.1"

我不是100%肯定,但名称似乎导致webpack在检测要包含哪些模块时遇到麻烦 在基于导入的包中。

导入有效后,名称THREE.OrbitControls将无法解析。 OrbitControls的NPM模块导出要调用的函数,使用 将现有THREE模块作为参数,然后添加OrbitControls。 很公平,但webpack初始化代码并不知道如何调用它 功能,我找不到办法。

以下内容会产生编译错误,但会产生确实有用的JS

import OrbitControls = require('three-orbitcontrols');
THREE.OrbitControls = OrbitControls(THREE);  // compile error but still emits JS that works

对于一个简单的想法,它似乎是很多的工作:重命名目录,黑客启动代码, 忽略编译时错误...

我突然意识到,我并不需要THREE成为捆绑中的一员,而且我并非真的 关心OrbitControls是否有类型。事实上,拥有一个较小的捆绑是 更快更好。

如何获取捆绑包的THREE ?只需声明external即可。那么 默认的NPM和typings模块工作正常。事实上,我甚至不确定typings 轨道或轨迹球控制需要模块。

答案 2 :(得分:0)

尝试上述操作并失败后,使用

"three": "^0.84.0",
"@types/three": "^0.83.0",
"three-js": ">=79.0.0",
"three-trackballcontrols": "0.0.5",
"webpack": "^1.14.0"

我做了以下事情:

npm install save-dev three-trackballcontrols
mkdir node_modules/@types/three-trackballcontrols
cd node_modules/@types/three-trackballcontrols
cp ../three/three-trackballcontrols.d.ts ./index.d.ts

接下来,在index.d.ts中,我将class TrackballControls extends EventDispatcher {...}更改为export class TrackballControls extends EventDispatcher {...}

之后,在index.d.ts中,在文件的末尾,我添加了

declare module "three-trackballcontrols" {
  export = THREE.TrackballControls;
}

接下来,我转到了three类型cd ../three,并修改了index.d.ts以将/// <reference path="three-trackballcontrols.d.ts" />更改为评论/* <reference path="three-trackballcontrols.d.ts" /> */

最后,在渲染器代码中,我使用import TrackballControls = require('three-trackballcontrols');并调用了controls = new TrackballControls(camera);而不是controls = new THREE.TrackballControls(camera);

答案 3 :(得分:0)

我收到了错误

错误类型错误: WEBPACK_IMPORTED_MODULE_1_three .TrackballControls不是构造函数

将我的项目更新为angular-cli 4.0之后。这是我的代码希望这可以帮助某人。

的package.json

"dependencies": {
    ...
    "three": "^0.82.1",
    "three-trackballcontrols": "0.0.5",
    ...
  },
"devDependencies": {
    ...
    "@types/three": "0.81.0",
    ...
  }

Component.ts

...
import * as THREE from 'three';
import TrackballControls from "three-trackballcontrols";
...
this.webGLRenderer = new THREE.WebGLRenderer({antialias: true});
this.camera        = new THREE.PerspectiveCamera(
            this.view_angle,
            this.width / this.height,
            this.near,
            this.far
        );
...
this.controls = new TrackballControls(this.camera, this.webGLRenderer.domElement);

答案 4 :(得分:0)

我也使用Angular CLI(Angular 4)并得到了同样的错误:

ERROR TypeError: __WEBPACK_IMPORTED_MODULE_1_three_trackballcontrols__.TrackballControls is not a constructor

使用与mok相同的代码,谢谢!

但是,我注意到这会产生错误:

import { TrackballControls } from 'three-trackballcontrols';

导入必须以这种方式完成(如mok所写):

import TrackballControls from 'three-trackballcontrols';