# Three.js r125 generates a warning in Observable

**URL:** <https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771>\
**Category:** Help\
**Created:** [March 12, 2021, 10:01pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771 "2021-03-12T22:01:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![severo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/severo/32/786_2.png) [@severo](https://talk.observablehq.com/u/severo)\
**Post date:** [March 12, 2021, 10:01pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/1 "2021-03-12T22:01:43Z")

</div>

three.js r125 got a small change: a warning is added to the console when various instances of THREE are present on the same page.

> <https://github.com/mrdoob/three.js/pull/21128/files>

I understand the idea because using three.js objects from different versions might be dangerous, but it’s even triggered when the versions are the same (which wastes resources but is not dangerous, afaik)

I wonder how it relates to Observable. Obviously, it’s common to import cells from various notebooks (that’s the idea), so if at least both of them make use of THREE, we get the warning. We might avoid this by creating an instance of THREE in the main notebook, then passing the instance to all the imported notebooks using `with {THREE}`, but it’s a mess!

I would be interested in your thoughts about this new feature and if you think that we should just accept to see this warning.

---

<div class="post-metadata">

**Author:** ![severo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/severo/32/786_2.png) [@severo](https://talk.observablehq.com/u/severo)\
**Post date:** [March 12, 2021, 10:04pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/2 "2021-03-12T22:04:41Z")

</div>

Note that tried to write a bit about a best practice here: [Import three.js / Sylvain Lesage / Observable](https://observablehq.com/@severo/three) but I’m not even sure it is a good idea 😕. Any comment is welcome

_Edit_: I wrote 4 possible ways to manage this. The first one is the normal way, which triggers the warning, but has most pros, I think.

---

<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:** [March 13, 2021, 11:08pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/3 "2021-03-13T23:08:30Z")

</div>

Apologies if I missed it, but it looks like none of your examples list the case where you simply import THREE from the respective notebook itself:

```auto
import {THREE} from '@severo/three-js-perspective-camera-utils'

```

Whenever I work with Zdog, I use helpers from [Zdog Helpers](https://observablehq.com/@mootari/zdog-helpers), so I just go ahead and import `Zdog` as well.

---

<div class="post-metadata">

**Author:** ![severo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/severo/32/786_2.png) [@severo](https://talk.observablehq.com/u/severo)\
**Post date:** [March 13, 2021, 11:17pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/4 "2021-03-13T23:17:33Z")

</div>

Sure, but the problem is when “you import three.js objects from two notebooks” (or more). If there is only one dependency, it’s OK.  
Another potential small problem is that you don’t have control on the version you will import.

---

<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:** [March 13, 2021, 11:37pm UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/5 "2021-03-13T23:37:03Z")

</div>

If it’s safe to ignore the warnings, then you could probably just mess with `window. __THREE__ ` after you imported the library.

Otherwise my first choice would probably be 3), passing in `THREE`. I’m not sure why you’d need to get the version number in this scenario:

- If you pass in THREE, you’re already in control.
- If you want to see the required version, you can inspect the notebook and optionally pin its version.

As for modules from examples, you’ll certainly have to restore any interface additions to the THREE object which are expected by the notebook (i.e., make sure all object types are available).

I’ve used the following format to deal with example modules:

```auto
function importExample(path, module = path.split('/').pop(), version = VERSION) {
  return import(`https://unpkg.com/three@${version}/examples/jsm/${path}.js`)
    .then(m => module ? m[module] : m);
}

```

```auto
OrbitControls = importExample('controls/OrbitControls')

```

```auto
Line2 = importExample('lines/Line2')

```

```auto
LineMaterial = importExample('lines/LineMaterial')

```

```auto
LineGeometry = importExample('lines/LineGeometry')

```

---

<div class="post-metadata">

**Author:** ![severo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/severo/32/786_2.png) [@severo](https://talk.observablehq.com/u/severo)\
**Post date:** [March 14, 2021, 12:14am UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/6 "2021-03-14T00:14:35Z")

</div>

> I’m not sure why you’d need to get the version number in this scenario

Because I was thinking to pass only THREE, not the modules from examples. Therefore I had to pass threeVersion, or get the version from the THREE object. I understand we don’t have the version as such, but the REVISION. I could get the version with “0.”+REVISION, but this schema might break in future versions of Three.

But you mention a good idea which is to attach the modules like OrbitControls to the THREE object. I was doing this, but changed recently, maybe for a bad reason. As these modules are imported dynamically as ESM, I thought it would be coherent to do the same for THREE. But:

```auto
THREE = {
  const THREE = await import(`https://unpkg.com/three@${threeVersion}/build/three.module.js`);
  const OrbitControls = (await import(`https://unpkg.com/three@${threeVersion}/examples/jsm/controls/OrbitControls.js`)).OrbitControls;
  THREE.OrbitControls = OrbitControls;
  return THREE;
}

```

generates an error: “THREE = TypeError: “OrbitControls” is read-only”. That’s why I switched to manage them as different objects in different cells, instead of adding them as properties of the THREE object.

If I rollback to importing THREE with require, it’s OK:

```auto
THREE = {
  const THREE = await require(`three@${threeVersion}`);
  THREE.OrbitControls = (await import(`https://unpkg.com/three@${threeVersion}/examples/jsm/controls/OrbitControls.js`)).OrbitControls;
  return THREE;
}

```

Thanks for your function importExample, it’s very nice, I will add it to the notebook.

So, finally, I think you’re right:

- in the application notebook, create the THREE instance with a chosen version and attaching it all the modules from examples that will be needed in the dependencies.
- pass THREE to all the dependencies (and so on transitively)

---

<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:** [March 14, 2021, 12:22am UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/7 "2021-03-14T00:22:09Z")

</div>

> [@severo](#):
>
> generates an error: “THREE = TypeError: “OrbitControls” is read-only”

Module objects are not extensible, which means that you cannot modify their shape. However, you might be able to “cheat” by destructuring into a new object:

```auto
return {...THREE, OrbitControls};

```

Note that I haven’t tested wether this method has any downsides.

---

<div class="post-metadata">

**Author:** ![severo](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/severo/32/786_2.png) [@severo](https://talk.observablehq.com/u/severo)\
**Post date:** [March 14, 2021, 1:15am UTC](https://talk.observablehq.com/t/three-js-r125-generates-a-warning-in-observable/4771/8 "2021-03-14T01:15:19Z")

</div>

OK, thanks for all @mootari. I reformulated the notebook: [Import three.js / Sylvain Lesage / Observable](https://observablehq.com/@severo/three)
