vasturiano / globe.gl

UI component for Globe Data Visualization using ThreeJS/WebGL
https://vasturiano.github.io/globe.gl/example/world-population/
MIT License
1.97k stars 293 forks source link

import dynamically #179

Open geshov opened 9 months ago

geshov commented 9 months ago

Please make variant of Globe.gl for the possibility of dynamic import in the browser:

const Globe = import("globe.gl.umd.js");

Thanks!

vasturiano commented 9 months ago

@geshov this module exports a ESM target at /dist/globe.gl.mjs, as you can see from the package.json file: https://github.com/vasturiano/globe.gl/blob/ad22dbe371f145e6433bf95e5706286c640ffcc9/package.json#L14

so you can import it in your browser if you prefer instead of the UMD target:

import Globe from '//unpkg.com/globe.gl/dist/globe.gl.mjs';
geshov commented 9 months ago

Thus, as shown above, the module is always imported, but I need to import the module by condition and from self hosting:

if (...) {
  const Globe = import("/globe/globe.gl.umd.js");
}

Thanks!

vasturiano commented 9 months ago

@geshov the target at /dist/globe.gl.min.js is already a UMD module, so you could use that.

geshov commented 9 months ago

the target at /dist/globe.gl.min.js is already a UMD module, so you could use that.

Have you tried dynamic import yourself? does it work for you?

I have a dynamic import of the library Globe.gl does not work, нere is the code based on your simple example:

    <script type="module">
      if (1 == 1) {
        const Globe = import("https://unpkg.com/globe.gl@2.30.0/dist/globe.gl.min.js");

        const N = 300;
        const gData = [...Array(N).keys()].map(() => ({
          lat: (Math.random() - 0.5) * 180,
          lng: (Math.random() - 0.5) * 360,
          size: Math.random() / 3,
          color: ["red", "white", "blue", "green"][
            Math.round(Math.random() * 3)
          ],
        }));

        Globe()
          .globeImageUrl("https://unpkg.com/three-globe/example/img/earth-night.jpg")
          .pointsData(gData)
          .pointAltitude("size")
          .pointColor("color")(document.getElementById("globe"));
      }
    </script>

Browser gives the following error:

Uncaught TypeError: Globe is not a function

If, as you claim, dynamic import should work, then what is my mistake, I will be grateful for clarification.

Thanks!

vasturiano commented 9 months ago

I have not had the necessity to perform dynamic conditional imports, but all I'm saying is that this package exports two target versions, an ESM and a UMD. That's all the package can be responsible for, in order to be imported by the consumers.

If you find something amiss in the syntax of these two exports, please report it. Otherwise there could be something wrong in the consumer import method.

geshov commented 9 months ago

I will return to my original request, which is reflected in the title of this issue:

Please make variant of Globe.gl for the possibility
of dynamic import in the browser:
const Globe = import("globe.gl.min.js");
Thanks!

It was a request, not a demand, so:

a) if you can help with this, then probably many will be grateful, because the library is quite large and under certain conditions it will help solve the performance problem.

b) if you don't want to do this, then write about it directly, without tricks, no one will be offended, since you already share your development for free.

Thanks!

vasturiano commented 9 months ago

@geshov I don't mind helping where I can, but I'm just not clear on specifically how such a target will be any different than the two already exposed, ESM and UMD.

geshov commented 8 months ago

If you can help, please make a version of the Globe.gl library that can be imported dynamically from self hosting:

const Globe = import("/globe/globe.gl.min.js");

Or add a working example of such an import to the documentation.

Thanks!

vasturiano commented 8 months ago

@gashov you can see here a working example of dynamically importing globe.gl, as an installed package in your app:

https://codesandbox.io/s/globe-dynamic-import-8zyhz7?file=/src/index.mjs

This uses the regular ESM target in the module.

What you were missing initially is that import is an async function which returns a promise, so you need to interpret it accordingly.

geshov commented 8 months ago

I tried to repeat your code with the library globe.gl.min.js:

import("https://unpkg.com/globe.gl@2.30.0/dist/globe.gl.min.js")
  .then(({ default: Globe }) => {
    Globe()(document.getElementById('globe'))
      .globeImageUrl('https://unpkg.com/three-globe/example/img/earth-blue-marble.jpg');
  });

The browser gives the same error:

Uncaught TypeError: Globe is not a function

My code differs from yours only in that it uses the library globe.gl.min.js, this means that the error lies in this place.

I still don't understand - which library should I use so that I can load it from my hosting and for this example to work?

Thanks!

vasturiano commented 8 months ago

Do you have an app with a package.json file? If so, you should be using the ESM form (.mjs), not the UMD (.min.js). And globe.gl should be in your app's dependencies list.

This is not specific to this module, it's how NPM dependencies work in general. Basically importing this package should work just like any other dependency of your app.

geshov commented 8 months ago

Here is a link to the documentation for the import() command, which, among other things, provides examples of dynamic import:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import

The documentation does not say anything about the fact that dynamic import works only in the Node.js (NPM) environment and requires the presence of the package.json file.

Here is an example from this documentation:

(async () => {
  if (somethingIsTrue) {
    // import module for side effects
    await import("/modules/my-module.js");
  }
})();

It's just a JS function, and it allows you to dynamically import modules prepared accordingly.

geshov commented 8 months ago

I independently found a solution for dynamically importing the Globe.gl library without Node.js (NPM) and without package.json .

You can close this issue, thanks!