Utilizing browser and CDNs to import modules in threejs and three-globe for seamless integration

As I delve into the world of threejs and three-globe, I encounter a challenge when trying to integrate them using CDN distributions from unpkg. The issue lies in dealing with modules, and I'm considering the possibility of incorporating a build tool despite initial reluctance.

My journey started with a straightforward example from the three.js README. Here's a snippet from my index.html:

<!DOCTYPE html>
<html lang="en">
        <head>
                <meta charset="utf-8">
                <title>Threejs basic app</title>
                <style>
                        body { margin: 0; }
                </style>

<script type="importmap">
        {
                "imports": {
                        "three": "https://unpkg.com/three/build/three.module.js"
                }
        }
</script>
        </head>
        <body>
                <script type="module" src="./main.js"></script>

        </body>
</html>

This setup works seamlessly. However, the challenge arises when attempting to include three-globe by importing it as suggested in the three-globe README:

import * as THREE from 'three';
import ThreeGlobe from 'https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e3a263c2b2b632922212c2b0e7c607d7e607e">[email protected]</a>/dist/three-globe.js';

const width = window.innerWidth, height = window.innerHeight;

// rest of the code is the same

Unfortunately, this leads to an error about the export named 'default' not being provided. Subsequent attempts using different import strategies also result in errors related to missing dependencies or conflicts with three.js. This brings me to ponder over the timing of object creation and potential asynchronous glitches with module loads.

While resorting to script tags instead of modules resolves some issues, it introduces new concerns like multiple instances of three.js being imported. Striving to mitigate this, I explore various import configurations in index.html and main.js, yet the persistent errors hint at the complexity of managing dependencies.

As I navigate through these challenges, I aspire to find a harmonious solution that allows seamless integration of threejs and three-globe without compromising on modularity and efficiency. The quest continues...

Answer №1

Just for your information, I successfully replicated the issue of importing multiple instances of Three.js and received the warning message. In my demonstration, I utilized the CDN and included the example script from the Three README directly as stackoverflow snippets do not support es modules.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script type="importmap">
      {
        "imports": {
          "three": "https://esm.sh/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="94e0fce6f1f1d4a4baa5a2a4baa5">[email protected]</a>",
          "three-globe": "https://esm.sh/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e6928e948383cb818a898483a6d4c8d5d6c8d6">[email protected]</a>"
        }
      }
    </script>
    <title>three.js CDN</title>
  </head>
  <body>
    <script type="module">
      import { PerspectiveCamera, Scene, BoxGeometry, MeshNormalMaterial, Mesh, WebGLRenderer } from 'three'
      import ThreeGlobe from 'three-globe'

      // console.log(ThreeGlobe)

      const width = window.innerWidth, height = window.innerHeight;

      // init

      const camera = new PerspectiveCamera( 70, width / height, 0.01, 10 );
      camera.position.z = 1;

      const scene = new Scene();

      const geometry = new BoxGeometry( 0.2, 0.2, 0.2 );
      const material = new MeshNormalMaterial();

      const mesh = new Mesh( geometry, material );
      scene.add( mesh );

      const renderer = new WebGLRenderer( { antialias: true } );
      renderer.setSize( width, height );
      renderer.setAnimationLoop( animation );
      document.body.appendChild( renderer.domElement );

      // animation

      function animation( time ) {

        mesh.rotation.x = time / 2000;
        mesh.rotation.y = time / 1000;

        renderer.render( scene, camera );

      }
    </script>
  </body>
</html>

Upon inspecting my browser's network panel, I observed that the 'three-globe' module was triggering an additional request for 'three' but at a different version (v0.158.0) than indicated in the importmap. This discrepancy in version between 'three' and 'three-globe' led to the duplication of instances.

One potential workaround is to explicitly specify 'three' in your importmap as showcased below.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script type="importmap">
      {
        "imports": {
          "three": "https://esm.sh/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c7b3afb5a2a287f7e9f6f2ffe9f7">[email protected]</a>",
          "three-globe": "https://esm.sh/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="07736f7562622a606b68656247352934372937">[email protected]</a>"
        }
      }
    </script>
    <title>three.js CDN</title>
  </head>
  <body>
    <script type="module">
      import { PerspectiveCamera, Scene, BoxGeometry, MeshNormalMaterial, Mesh, WebGLRenderer } from 'three'
      import ThreeGlobe from 'three-globe'

      // console.log(ThreeGlobe)

      const width = window.innerWidth, height = window.innerHeight;

      // init

      const camera = new PerspectiveCamera( 70, width / height, 0.01, 10 );
      camera.position.z = 1;

      const scene = new Scene();

      const geometry = new BoxGeometry( 0.2, 0.2, 0.2 );
      const material = new MeshNormalMaterial();

      const mesh = new Mesh( geometry, material );
      scene.add( mesh );

      const renderer = new WebGLRenderer( { antialias: true } );
      renderer.setSize( width, height );
      renderer.setAnimationLoop( animation );
      document.body.appendChild( renderer.domElement );

      // animation

      function animation( time ) {

        mesh.rotation.x = time / 2000;
        mesh.rotation.y = time / 1000;

        renderer.render( scene, camera );

      }
    </script>
  </body>
</html>

I have yet to determine the reason why 'three-globe' relies on that specific version of 'three'. I noticed that 'three' is specified as a peerDependency, but I haven't delved into the build or deployment specifics.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for including subjects in JSON data

I am trying to include the subject in JSON data so that I can fetch it using $.each(data.subject). Below is my API code where I am retrieving all the data encoded in JSON format. Any assistance would be greatly appreciated. [{"id":"79","FirstName":"Elon", ...

Attempted to execute my testing script with mocha, however encountered a "Reference Error: beforeEach is not defined" issue

While running my test script for a todo app in node.js using Mocha, I encountered a reference error stating that "beforeEach is not defined". The code snippet causing the issue is shown below: const {app} = require('./../server'); const {Todo} ...

Is it possible to merge string and span elements to create a unified element?

In my current project using React, I am dealing with an array of strings and JSX Elements. For instance, the array has items like: [<span class="name">JCrew0</span>, "edited this document"]. I am attempting to display thes ...

Flexbox helps create responsive layouts with ease

Utilizing flex to centrally position my element within my layers has worked well for me, but I encountered an issue when switching to a smaller screen size. The element simply scales down in size instead of taking up the full width like it does with Bootst ...

In Node.js Express, the download window won't pop up unless the entire file has been sent in the header response

I have been using Express to develop an API that allows users to download PDF files. The download process is functioning correctly, but I am facing an issue where the download window, which prompts me to select a destination folder for the download, only a ...

emailProtected pre-publish: Running `python build.py && webpack` command

i am currently using scratch-blocks through the Linux terminal I have encountered a problem which involves running the following command: python build.py && webpack [email protected] prepublish: python build.py && webpack Can anyon ...

Articles related to Express.js - encountering issues when attempting to read properties from a null object

I'm trying to display related articles based on categories using Mongoose for querying data from MongoDB. However, when I attempt the code below, I encounter an error message stating "TypeError: Cannot read properties of null (reading 'category& ...

Master the art of utilizing angular-filter

Encountering some challenges while attempting to utilize angular-filter: The following links have been imported into the HTML file: <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script> <script src=" ...

Is there a way to customize the look of the time selected in the <input matInput type="time" step="1" /> time picker?

Currently, I am utilizing the following code as a time picker in my Angular 9 application. My goal is to modify the selected time's color to a bright blue shade. How can I accomplish this task? <input matInput type="time" step="1&quo ...

Pairing a removal request with a JSON entity

I am currently working on a project where I need to delete a specific JSON object from a JSON file once its values are displayed in a form using the AJAX Delete function. In order to achieve this, I have set up a route in Express for the JSON file as shown ...

I am facing difficulties displaying the egin{cases}…end{cases} equation using Jekyll's MathJax

MathJax is used on our course website. We have implemented MathJax in Jekyll and hosted it on GitHub pages. While MathJax works well for simple equations, I have faced difficulties with more complex ones. Despite spending hours investigating and experiment ...

Reverse row changes in Angular Ag-Grid with the click of a button

Developed using Angular and JavaScript technologies. The AG-Grid consists of editable records with the first column being a checkbox. When changes are made to any selected records, clicking on a particular record's checkbox and then pressing a button ...

multiples of order quantities in WooCommerce

In order to implement a minimum order quantity based on category, I came across this code. However, it seems to apply to all products in the cart. What additional modifications would be needed to specify certain categories? My objective is for customers t ...

Guide to ensuring the navbar remains at the top of the webpage following an image

I am attempting to create a sticky navbar that stays at the top of the page once the header has been scrolled past. It should have a similar effect as shown in this example on codepen.io, but with the addition of an image that stretches across most of the ...

Swap out the div block with a new one

I am currently facing an issue with my JavaScript code. The code is supposed to remove block1 and replace it with block2 when an onclick function is triggered. function buyerclick() { div = document.getElementById('block2'); div.style.displa ...

Using jQuery to fetch and read the source code of a specified URL

I'm facing an issue with extracting the source code of a website URL into a variable. Here is my current approach: <script type="text/javascript"> debugger; $(documnet).ready(function () { var timer = $.ajax({ type: ...

"Enhancing User Experience with jQuery: Implementing a Smooth Scroll Feature with Current

I could really use some guidance on this issue that's been causing me trouble. Take a look at this fiddle for reference: http://jsfiddle.net/NtUpw/ Currently, the code is functioning as expected. However, I'm facing an issue where when the curre ...

Determine the SVG arc connecting two given points

My situation involves having coordinates for points X and A, A',... as follows: X [x,y] (starting point) A [a,b], A'[a',b'], etc. (ending points) I also have information about angles XCA, XCA', etc. However, I am struggling t ...

Add the Selected Value to the Title

Is there a way to dynamically add the selected value from each select element to its corresponding heading without requiring user interaction? I need this to happen as soon as the page loads. Here is an example in a jsfiddle https://jsfiddle.net/dqfvyvdt/2 ...

Event triggered only upon initial click

I am experiencing an issue with my category list. When I click on a category to trigger an AJAX request for the first time, the request does not go through. However, when I click on the same category a second time, it works perfectly. Below is the code sni ...