使用webpack、threejs示例和typescript?

13

我在使用webpack和typescript时,发现很难让threejs的示例(如EffectComposer或Detector)正常工作。

首先,相关的*.d.ts文件都已经存在并通过tsd安装。我的问题是让webpack实际包含默认threejs构建之外的文件(即examples/js/中的内容)。

通过从npm安装three,我可以执行以下操作:

import THREE = require('three');

这个方案可以正常工作,但缺乏前面提到的所有好处。npm上有一些其他的threejs包,捆绑了插件,但我认为它们无法与typescript一起使用(因为typescript编译器会拒绝require('three-js')(['EffectComposer']))。

是否有人能够让此包中的某些内容(如后处理)与typescript配合使用?

4个回答

11

我成功地在webpack.config.js中找到了一种相当干净的方法来设置它。

根据丹的回答:

$ npm install --save-dev imports-loader

事实证明,我们实际上不需要exports-loader,因为three.js示例将其构造函数添加到THREE对象中。

然后,在webpack.config.js中,如果模块的路径解析为包含three/examples/js的任何内容,我们可以添加一条规则来将var THREE = require('three');添加到已导入的模块中:

module: {
  rules: [
    ...
    {
      test: /three\/examples\/js/,
      use: 'imports-loader?THREE=three'
    }
  ]
}

现在,示例模块将在期望时找到全局变量THREE。

为了使导入示例的过程更加简洁:

resolve: {
  alias: {
    'three-examples': path.join(__dirname, './node_modules/three/examples/js')
  },
  ...
},
这假设 webpack.config.jsnode_modules 在同一目录下,请根据情况进行调整。
现在,我们可以像这样使用示例文件:
import * as THREE from 'three';
import 'three-examples/controls/OrbitControls';

导入模块以获得其副作用。

如果您在使用Typescript和/或Babel时收到有关示例模块在THREE上未找到的警告,则可以参考imports-loader存储库上的此问题


1
请问您能否提供完整的webpack配置,包括resolve部分应该放在哪里? - tomriddle_1234
我有一堆无关的细节在我的代码中,但是根据 https://webpack.js.org/configuration/ ,它们应该在 module.exports 的顶层,与 module 并列。 - Chris Williamson
对我来说,只有使用“const THREE = require('three');”才能正常工作。 - DevMultiTech
它可以运行,但那个警告真的让我很烦恼 - 你找到解决办法了吗? - rpadovani
@rpadovani,我不确定你指的是哪个警告。你是指Jokester答案中提到的那个吗? - Chris Williamson

8
这是我亲身实践有效的方法。
$ npm install --save-dev exports-loader imports-loader

然后,要使用来自three/examples/js的内容,我会这样做:
const THREE = require('three');
// imports provides THREE to the OrbitControls example
// exports gets THREE.OrbitControls
THREE.OrbitControls = require('imports?THREE=three!exports?THREE.OrbitControls!../../node_modules\/three\/examples\/js\/controls\/OrbitControls');

// use THREE.OrbitControls ...

我认为正确的做法是使用 importsexports 加载器,通过配置文件使用,而不是在 require 中嵌入它们。当我有示例时,我会更新这个答案。


这仍然有效,尽管我省略了 THREE.OrbitControls = 部分。最好将其放在 webpack.config 中而不是代码文件中,但我很难让它正常工作。 - Josh Santangelo
在配置文件中找到了一种方法,详见下面的答案。 - Chris Williamson

4

我能够将OrbitControls与(webpack v2 + ts-loader)捆绑在一起,不需要其他加载器。

package.json:

"dependencies": {
    "three": "^0.85.2",
    "@types/three": "^0.84.12",
    "ts-loader": "^2.1.0",
    "typescript": "^2.3.4",
    "webpack": "^2.6.1"
},

entrypoint.ts:

import * as THREE from "three";

// OrbitControls.js expects a global THREE object
(window as any).THREE = THREE;

// NOTE: OrbitControls must be included with require:
// using "import" cause it to be executed before global THREE becomes available
require("three/examples/js/controls/OrbitControls");

// ... code that uses THREE and THREE.OrbitControls

注意:webpack可能会发出警告,如"export 'OrbitControls' (imported as 'THREE') was not found in 'three',因为OrbitControls.js不是一个正确的JS模块。 我们可以无视这个警告。


1
我将尝试回答您关于TypeScript和ThreeJS在IDE中集成的问题。
正如您所见,大多数组件都托管在DefinitelyTyped档案中。我建议停止使用tsd并迁移到typing。
下面列出了一个基本的typings.json,可以被typing消耗。它获取最新的主ThreeJS和effect composer库,以便被TypeScript识别。请注意,随着.tsd的演变,提交的标签将会改变。
{
  "ambientDependencies": {
    "three": "github:DefinitelyTyped/DefinitelyTyped/threejs/three.d.ts#c6c3d3e65dd2d7035428f9c7b371ec911ff28542",
    "three-projector": "github:DefinitelyTyped/DefinitelyTyped/threejs/three-projector.d.ts#48f20e97bfaf70fc1a9537b38aed98e9749be0ae",
    "three-detector": "github:DefinitelyTyped/DefinitelyTyped/threejs/three-effectcomposer.d.ts#48f20e97bfaf70fc1a9537b38aed98e9749be0ae",
    "three-effectscomposer": "github:DefinitelyTyped/DefinitelyTyped/threejs/detector.d.ts#48f20e97bfaf70fc1a9537b38aed98e9749be0ae",
    "three-shaderpass": "github:DefinitelyTyped/DefinitelyTyped/threejs/three-shaderpass.d.ts#ee05b1163d8da7f16719f08d52f70ab524f1003a"
  }
}

附上一个IDE截图,显示了EffectsComposer的公共方法。您可能还想尝试不同的TypeScript模块加载器功能。

TypeScript within the IDE recognizes the ThreeJS libraries


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