Setting up Three.js

I’m trying to learn Three.js. It looks like the newest version of three only uses ES6 modules in away that the standard example by Observable doesn’t support. I tried a number of things before I found something that seems to work. Is this the correct way to get it going in ObservableHQ?

THREE = {
  const THREE = await import('three@0.155.0/build/three.module.js?module');
  const oc = await import('https://unpkg.com/three@0.155.0/examples/jsm/controls/OrbitControls.js?module');
  const extendedTHREE = { ...THREE, OrbitControls: oc.OrbitControls };
  return extendedTHREE;
}

https://observablehq.com/d/383984bd7470caba

That looks about right to me.

Unfortunately there’s no good way to use import maps in notebooks yet (as recommended by Three’s CDN example), but for more complex dependencies (e.g. shaders or postprocessing passes) you could use esm.sh’s custom bundles:

THREE = (await (await import("https://esm.sh/build")).esm`
  import * as THREE from "three@0.155.0";
  import {OrbitControls} from "three@0.155.0/examples/jsm/controls/OrbitControls.js";
  export default {...THREE, OrbitControls};
`).default

However, I’d argue that merging example classes into the THREE object is a thing of the past, now that Three.js has moved all examples to ES modules. My recommendation would be to just import helpers in separate cells:

THREE = import("three@0.155.0")
OrbitControls = (await import("three@0.155.0/examples/jsm/controls/OrbitControls.js")).OrbitControls

As long as the versions match (and you’re not using skypack which bundles all dependencies) THREE should only be loaded once.

3 Likes