I\'m having a lot of trouble getting stuff in threejs\'s examples (like EffectComposer or Detector) to work with webpack and typescript.
First off the relevant *.d
I will try to answer just the part of your question regarding TypeScript and ThreeJS integration within your IDE.
As you've seen, most of the components are hosted on the DefinitelyTyped archives. I do recommend stop using tsd
and migrate to typing
.
A basic typings.json
that typing
will consume is listed below. It gets the latest main ThreeJS and the effect composer library to be recognized by TypeScript. Note the commit hashtags will change as the .tsd
evolves.
{
"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"
}
}
Attached is a snapshot of an IDE recognizing the public methods of the EffectsComposer. You may want to also experiment with different module loader capabilities of TypeScript.
I was able to bundle OrbitControls with (webpack v2 + ts-loader) and no other loaders.
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
NOTE: webpack may warn like "export 'OrbitControls' (imported as 'THREE') was not found in 'three'
, because OrbitControls.js
is not a proper JS module. I suppose we can just ignore this warning.
I managed to find a pretty clean way to set this up in webpack.config.js
.
As per Dan's answer:
$ npm install --save-dev imports-loader
It turns out we don't actually need exports-loader
, since the three.js examples add their constructors to the THREE
object.
Then, in webpack.config.js
, we can add a rule to add var THREE = require('three');
to an imported module if the module's path resolves to anything containing three/examples/js
:
module: {
rules: [
...
{
test: /three\/examples\/js/,
use: 'imports-loader?THREE=three'
}
]
}
Now the example modules will find the THREE global when they expect it.
Then, to make importing examples a little less verbose:
resolve: {
alias: {
'three-examples': path.join(__dirname, './node_modules/three/examples/js')
},
...
},
This assumes that webpack.config.js
is in the same directory as node_modules
, adjust accordingly.
Now, we can use the example files like so:
import * as THREE from 'three';
import 'three-examples/controls/OrbitControls';
to import the module for its side-effects.
If you're using this with Typescript and/or Babel and are getting warnings about the example module not being found on THREE
, you may find this issue on the imports-loader
repository useful to reference.
Here's what worked for me.
$ npm install --save-dev exports-loader imports-loader
Then, to use something from three/examples/js
, I do this:
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 ...
I think the right thing to do is use the imports
and exports
loaders by config rather than embedding them in the require. I'll update this answer when I have an example.