Stanislav Khromov

Having just started on a new SvelteKit project, I was tasked with implementing a Leaflet component.

Using Leaflet in SvelteKit is a bit tricky due to its dependency on the window object and the way SvelteKit builds its production bundle, but it is fully possible, so let’s do that in this post. We’re going to assume that you have a working SvelteKit app. If not, follow the official guide first!

Let’s start out by installing leaflet:

npm i leaflet

Now we can create a simple Svelte component based on the Leaflet Quick Start guide!

Create the file src/lib/LeafletMap.svelte

<script>
    import { onMount, onDestroy } from 'svelte';
    import { browser } from '$app/env';

    let mapElement;
    let map;

    onMount(async () => {
        if(browser) {
            const leaflet = await import('leaflet');

            map = leaflet.map(mapElement).setView([51.505, -0.09], 13);

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

            leaflet.marker([51.5, -0.09]).addTo(map)
                .bindPopup('A pretty CSS3 popup.<br> Easily customizable.')
                .openPopup();
        }
    });

    onDestroy(async () => {
        if(map) {
            console.log('Unloading Leaflet map.');
            map.remove();
        }
    });
</script>


<main>
    <div bind:this={mapElement}></div>
</main>

<style>
    @import 'leaflet/dist/leaflet.css';
    main div {
        height: 800px;
    }
</style>

Finally, add your new component to your src/routes/index.svelte file:

<script>
	import LeafletMap from '$lib/LeafletMap.svelte';
</script>

<main>
	<LeafletMap />
</main>

Now it’s time to start the dev server with npm run dev and visit http://localhost:3000/ to marvel at the results:

Web Developer at Aftonbladet (Schibsted Media Group)

View Comments

  • OliverOliver

    Author Reply

    Thanks for sharing! I could also load the css from the installed NodeJS module using

    @import 'leaflet/dist/leaflet.css';


  • BrayBray

    Author Reply

    great job! simple and straight to the point!


  • gdgd

    Author Reply

    Great post! I’m trying to make working leaflet.markercluster based on your example.
    How would you import it in onMount? Here is a basic example:
    https://jsbin.com/fimaxap/2/edit?html,js,output


    • Hi gd!

      There’s nothing special about markercluster or any Leaflet library, you can use them normally inside onMount. The only quirk is how Leaflet plugins are loaded and how that interacts with ES6 imports, but that’s not SvelteKit-specific.

      I made an example with normal Svelte, as there is no REPL playground for SvelteKit, but it should be the same except for the browser check in SK:
      https://svelte.dev/repl/761fc7956ca3499888545613f54a9146?version=3.53.1


      • gdgd

        Author

        Thanks Stanislav for the answer and the REPL! A bit before receiving your reply, I finally made it working in SK with onMount and if (browser). Now the only tricky thing with onMount is that I have reactive data that generates the markers. And the reactive statement $: doesn’t work in onMount… Any idea how to pass reactive data into that? Many thanks in advance


      • Hi gd,

        You are right, you can not do reactive things in onMount, as it runs only once. What you need to do is initialize the map in onMount and then create a reactive statement outside onMount that only triggers if you have mounted. I made an example below that allows you to remove points from the map with a button. The actual removal of markers is something Leaflet-specific. Every time the markers data changes, we remove the old markers group from the leaflet map and add a new one with the current marker data. You can see it here:
        https://svelte.dev/repl/521971715dde45c8b11eee45a48400b8?version=3.53.1

        PS. To make things easier for you in SvelteKit, you can disable SSR for a specific route as per the documentation below. If you don’t care about SSR for SEO purposes, this can make things easier for you as you can just pretend it’s a normal client-side rendered Svelte page:
        https://kit.svelte.dev/docs/page-options#ssr


Next Post