Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import issues with npm package vs github cdn content #143

Open
GeorgeNavQS opened this issue Dec 7, 2024 · 3 comments
Open

Import issues with npm package vs github cdn content #143

GeorgeNavQS opened this issue Dec 7, 2024 · 3 comments

Comments

@GeorgeNavQS
Copy link

GeorgeNavQS commented Dec 7, 2024

When utilizing this file (referenced from https://github.com/maptiler/cdn.maptiler.com/tree/main/maptiler-sdk-js/latest), the import works, I'm able to render the map successfully as expected, but the types are out of whack

https://raw.githubusercontent.com/maptiler/cdn.maptiler.com/refs/heads/main/maptiler-sdk-js/latest/maptiler-sdk.umd.js

My use case is below (deno fresh app which utilizes preact). I am doing some delayed importing so it imports client side.

import { IS_BROWSER } from "$fresh/runtime.ts";
import { useEffect, useRef } from "preact/hooks";

const tokyo = { lng: 139.753, lat: 35.6844 };

export const UserMap = (props: { className?: string }) => {
  const mapContainerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!IS_BROWSER) {
      console.error("IS_BROWSER is false");
      return;
    }

    if (typeof window === "undefined") {
      console.error("window is undefined");
      return;
    }

    const ref = mapContainerRef.current;
    if (!ref) {
      console.error("mapContainerRef.current is null");
      return;
    }

    (async () => {
      try {
        // ref: https://github.com/maptiler/cdn.maptiler.com/tree/main/maptiler-sdk-js/latest
        const maptilerSdk = await import("@maptiler/sdk");
        maptilerSdk.default.config.apiKey = "???";
        const { Map, MapStyle } = maptilerSdk.default;
        new Map({
          container: ref,
          // style: MapStyle.STREETS,
          center: [tokyo.lng, tokyo.lat],
          zoom: 14, // starting zoom
        });
      } catch (error) {
        console.error("Failed to load @maptiler/sdk:", error);
      }
    })();
  }, [mapContainerRef.current, IS_BROWSER]);

  return (
    <div
      ref={mapContainerRef}
      id="map"
      className={`flex ${props.className ?? ""}`}
    />
  );
};

image

When using npm, the types are nice, but it fails to import due to some relative import issues
TypeError: Failed to resolve module specifier "events". Relative references must start with either "/", "./", or "../".

I understand this is a pretty niche problem so if you need anymore info let me know

@jonathanlurie
Copy link
Collaborator

Hey, I am not sure I totally understand the situation. It looks like you are working on a frameworks that attempts at doing SSR and you don't want the SDK to be part of the SSRed bundle.
In any case, I would strongly discourage to use the UMD bundle in this context as its main goal is to be used from vanilla JS in a basic HTML page.

Is the events import what's failing on server side for you? It's supposed to work on all platforms but when I read at the source there are bits that are run on top level, without calling any function so just importing it would run those bits, and that's what may cause the issue. I'll create a ticket internally to look more carefully into it and see if we can use any alternative.

One thing maybe you could do (but that I've never tried) is to import only the types synchronously, and then async import the module and somehow bind the types with the corresponding instances using as.

import type { Map as MapSDK } from "@maptiler/sdk";

Let us know of your progress, with more and more frameworks doing SSR, this kind of situation will become increasingly popular.

@jonathanlurie
Copy link
Collaborator

Very possibly Deno and the Events lib don't play well together, possibly because Deno already has an Event import from its core/standard-library so it's being confused at this package import. Since the Event library imported in the SDK has been last published 4 years ago, it was definitely not made for Deno. That's another argument to maybe remove it from SDK...

@GeorgeNavQS
Copy link
Author

GeorgeNavQS commented Dec 11, 2024

Hey, I am not sure I totally understand the situation. It looks like you are working on a frameworks that attempts at doing SSR and you don't want the SDK to be part of the SSRed bundle. In any case, I would strongly discourage to use the UMD bundle in this context as its main goal is to be used from vanilla JS in a basic HTML page.

Is the events import what's failing on server side for you? It's supposed to work on all platforms but when I read at the source there are bits that are run on top level, without calling any function so just importing it would run those bits, and that's what may cause the issue. I'll create a ticket internally to look more carefully into it and see if we can use any alternative.

One thing maybe you could do (but that I've never tried) is to import only the types synchronously, and then async import the module and somehow bind the types with the corresponding instances using as.

import type { Map as MapSDK } from "@maptiler/sdk";

Let us know of your progress, with more and more frameworks doing SSR, this kind of situation will become increasingly popular.

Ah, this worked like a charm. I have my types now. Thanks man! Of course this probably has problems, but at least I have usable types in the short term. Thanks for looking into this.

deno.json (basically deno's version of package.json)

{
  // ...
  "imports": {
    "@maptiler/sdk": "npm:@maptiler/sdk@2.5.0",
    "@maptiler/sdk-web": "https://raw.githubusercontent.com/maptiler/cdn.maptiler.com/refs/heads/main/maptiler-sdk-js/v2.5.0/maptiler-sdk.umd.js",
  },
  // ...
}

Updated file

import { IS_BROWSER } from "$fresh/runtime.ts";
import { useEffect, useRef } from "preact/hooks";
import type mtSdk from "@maptiler/sdk";

const tokyo = { lng: 139.753, lat: 35.6844 };

export const UserMap = (props: { className?: string }) => {
  const mapContainerRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!IS_BROWSER) {
      console.error("IS_BROWSER is false");
      return;
    }

    if (typeof window === "undefined") {
      console.error("window is undefined");
      return;
    }

    const ref = mapContainerRef.current;
    if (!ref) {
      console.error("mapContainerRef.current is null");
      return;
    }

    (async () => {
      try {
        // ref: https://github.com/maptiler/cdn.maptiler.com/tree/main/maptiler-sdk-js/latest
        const maptilerSdk = (await import("@maptiler/sdk-web"))
          .default as (typeof mtSdk);
        maptilerSdk.config.apiKey = "???????";
        const { Map } = maptilerSdk;
        const map = new Map({
          container: ref,
          // style: MapStyle.STREETS,
          center: [tokyo.lng, tokyo.lat],
          zoom: 14, // starting zoom
        });
      } catch (error) {
        console.error("Failed to load @maptiler/sdk:", error);
      }
    })();
  }, [mapContainerRef.current, IS_BROWSER]);

  return (
    <div
      ref={mapContainerRef}
      id="map"
      className={`flex ${props.className ?? ""}`}
    />
  );
};

"Is the events import what's failing on server side for you?" - Yup

"I'll create a ticket internally to look more carefully into it and see if we can use any alternative." - Thanks man!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants