Check out this more recent tutorial. At the end of this post, you'll find information on the updates.
In summary, three.js now emphasizes using es6 modules. So instead of
<script src="three.js"></script>
<script src="GLTFLoader.js"></script>
<script>
let scene,camera,renderer;
function init(){
...
THREE.GLTFLoader.load(...
you should use
<script type="module">
import * as THREE from './build/three.module.js';
import {GLTFLoader} from './examples/jsm/loaders/GLTFLoader.js';
let scene,camera,renderer;
function init(){
...
GLTFLoader.load(...
To implement it like that, you need to copy the three.js files to match the folder structure shown.
someFolder
|
├-build
| |
| +-three.module.js
|
+-examples
|
+-jsm
|
+-controls
| |
| +-OrbitControls.js
| +-TrackballControls.js
| +-...
|
+-loaders
| |
| +-GLTFLoader.js
| +-...
|
...
If you prefer the old method with <script>
tags, make sure to use files from the js
folder, not the jsm
folder.
Note: It's important to maintain this folder structure because files in the examples/jsm folder, like GLTFLoader.js
, reference other files with relative but hardcoded paths. For example, in GLTFLoader.js, there's a line that looks like:
import {stuff} from "../../../build/three.module.js";
Some benefits of the new format include
Modules can pull in their needed parts easily. In the past, one additional part could require multiple <script>
tags, now it's just 1 import that handles everything.
Your webpage builder can strip out unused parts with ease.
There are talks about phasing out the <script>
approach entirely in the future.
Let's clarify why ES6 modules are better and how the consistent folder structure is crucial.
Prior to r105, to use EffectComposer, you'd do
<script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
You'd encounter an error
THREE.EffectComposer relies on THREE.CopyShader
You'd have to manually add dependencies like
<script src="threejs/examples/js/postprocessing/EffectComposer.js"></script>
<script src="threejs/examples/js/shaders/CopyShader.js"></script>
Now, thanks to es6 modules from r105 onwards, you can simply write
import {EffectComposer} from './threejs/examples/jsm/postprocessing/EffectComposer.js';
which is much cleaner. The ES6 module version of EffectComposer.js
manages its own dependencies, making the process seamless. Check the top of EffectComposer.js for references to its requirements.
import {
Clock,
LinearFilter,
Mesh,
OrthographicCamera,
PlaneBufferGeometry,
RGBAFormat,
Vector2,
WebGLRenderTarget
} from "../../../build/three.module.js";
import { CopyShader } from "../shaders/CopyShader.js";
import { ShaderPass } from "../postprocessing/ShaderPass.js";
import { MaskPass } from "../postprocessing/MaskPass.js";
import { ClearMaskPass } from "../postprocessing/MaskPass.js";
As seen above, EffectsComposer.js
expects certain folders to be in specific locations, affirming the importance of maintaining consistent folder structure.