Sunday | 23 JUN 2024
[ previous ]
[ next ]

Adding 3rd Party Scripts to Sveltekit

Title:
Date: 2023-04-09
Tags:  

Using sveltekit with browser libraries is a bit of a pain. You can get around the issue by simply adding scripts to the main src/app.html and this works pretty well. However this means the scripts are loaded for every page, even when they aren't needed. This is why we need to load these scripts specifically on the component that needs it.

This however also means we don't want to add these scripts to the specific component because that component might appear multiple times. This would then include the same script multiple times.

An example of this is something like using pdfjs. I want to create a page that contains multiple PDFs being displayed. This requires the component to use the pdfjs library in the browser. I could bake the 3rd party scripts on the component level but that would load things many times or I would need to add a check to the component so that it doesn't always load the script.

My preferred solution is to add the 3rd party scripts to the main page and then load the PDFs once the 3rd party scrips are loaded.

You can do this by:

<script>
    let pdf = null;
    let loadedPDF = false;
    
    onMount(async () => {
        let pdfScript = document.createElement("script");
        pdfScript.src = "/assets/pdfjs/build/pdf.js";
        document.head.appendChild(pdfScript);
        
        pdf = window['pdfjs-dist/build/pdf'];
        if (pdf) {
            pdf.GlobalWorkerOptions.workerSrc = '/assets/pdfjs/build/pdf.worker.js';
            loadedPDF = true;
        } else {
            const checkPDF = setInterval(() => {
                pdf = window['pdfjs-dist/build/pdf'];
                if (pdf) {
                    pdf.GlobalWorkerOptions.workerSrc = '/assets/pdfjs/build/pdf.worker.js';
                    loadedPDF = true;
                    clearInterval(checkPDF);
                }
            }, 100);
        }
    });
</script>

The first thing we do is set up the pdf variable which will contain the pdfjs library and a loaded flag that will tell us if the pdfjs library is loaded.

When the page is in the browser and it is loading, we will create a script tag, add the javascript library we want and then we append it to the document head. This will cause the javascript to get evaluated and loaded in.

We then check if the library is loaded into the window object, if it isn't there, then we will check on an interval of every 100ms. This way we will give it some time before we check for the library.

If we find the library, then we set the loaded flag and clear the interval.

This is a simple way of loading libraries using sveltekit.

I wish there was a better way however as it feels quite dirty and I think there must be a better way. I tried using the browser variable from $app/environment but that didn't seem to work the way I wanted it to.