sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.43k stars 1.88k forks source link

LeafletJS fails to load image after build #8202

Closed mike-lloyd03 closed 1 year ago

mike-lloyd03 commented 1 year ago

Describe the bug

I'm writing an app that uses LeafletJS to render a map on the page. In dev, this map loads correctly with a pin on the user's location (the icon for the pin is being loaded from node_modules). But when I deploy using the node adapter (in a docker container) the image for the pin fails to load with a 404 error. It attempts to load the image from https://unpkg.com/leaflet@1.9.3/distmarker-icon.png but it should be getting it from https://unpkg.com/browse/leaflet@1.9.3/dist/images/marker-icon.png. How can I get it to load from the right URL or alternatively, how can I get it to load from the filesystem?

I'm using SvelteKit 1.0, node-adapter 1.0.0, and vite 4.0.0.

Reproduction

<script lang="ts">
    import { onMount, onDestroy, afterUpdate } from "svelte";
    import type { Map, Marker } from "leaflet";

    export let coords: [number, number];
    export let radius: number;

    let mapElement: HTMLElement;
    let map: Map;
    let marker: Marker;

    onMount(async () => {
        const L = await import("leaflet");

        if (mapElement) {
            map = L.map(mapElement).setView(coords, radius);

            L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
                attribution: '<a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
            }).addTo(map);

            marker = L.marker(coords).addTo(map);
        }
    });

    onDestroy(async () => {
        if (map && marker) {
            marker.remove();
            map.remove();
        }
    });

    afterUpdate(async () => {
        if (map && marker) {
            map.setView(coords, radius);
            marker.setLatLng(coords);
        }
    });
</script>

<div id="map" bind:this={mapElement} />

<style>
    @import "leaflet/dist/leaflet.css";
    #map {
        height: 24rem;
        z-index: 1;
    }
</style>

Logs

No response

System Info

System:
    OS: Linux 6.0 Arch Linux
    CPU: (16) x64 Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz
    Memory: 52.44 GB / 62.67 GB
    Container: Yes
    Shell: 0.72.0 - /usr/bin/nu
  Binaries:
    Node: 16.18.0 - /usr/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Chromium: 107.0.5304.110
    Firefox: 106.0.5
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.88 
    @sveltejs/adapter-node: ^1.0.0 => 1.0.0 
    @sveltejs/kit: ^1.0.0 => 1.0.0 
    svelte: ^3.44.0 => 3.55.0 
    vite: ^4.0.0 => 4.0.1

Severity

annoyance

Additional Information

No response

jasonlyu123 commented 1 year ago

Please use svelte discord or stack overflow for support questions. Leaflet is using some runtime detection for loading the default marker and it doesn't work well with bundler. You can set the iconUrl in the icon option to a CDN url, Or you can import the icon and pass it to the iconUrl option

import markerIcon from 'leaflet/dist/images/marker-icon.png';
mike-lloyd03 commented 1 year ago

I tried asking in the Discord first but got no response. Thanks for pointing me in the right direction.