# Setting up Three.js

**URL:** <https://talk.observablehq.com/t/setting-up-three-js/8182>\
**Category:** Help\
**Created:** [August 13, 2023, 4:54am UTC](https://talk.observablehq.com/t/setting-up-three-js/8182 "2023-08-13T04:54:46Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![joesquito](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/joesquito/32/7157_2.png) [@joesquito](https://talk.observablehq.com/u/joesquito)\
**Post date:** [August 13, 2023, 4:54am UTC](https://talk.observablehq.com/t/setting-up-three-js/8182/1 "2023-08-13T04:54:46Z")

</div>

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?

```auto
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](https://observablehq.com/d/383984bd7470caba)

---

<div class="post-metadata">

**Author:** ![mootari](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/mootari/32/581_2.png) [@mootari](https://talk.observablehq.com/u/mootari)\
**Post date:** [August 13, 2023, 9:14am UTC](https://talk.observablehq.com/t/setting-up-three-js/8182/2 "2023-08-13T09:14:29Z")

</div>

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](https://esm.sh/#docs)’s custom bundles:

```auto
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:

```js
THREE = import("three@0.155.0")

```

```js
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.
