Enhance Performance of Svelte Application by using Partytown for 3rd party scripts



Why we need Analytics?

Insights and data from website analytics can be used to improve the user experience for website visitors. In order to optimize a website for important conversion metrics, it is also essential to understand users behaviors.

What's the Trade-off?

Out of all the JavaScript supplied on a website, third party analytics scripts like "Google Tag Manager" can have the biggest detrimental effect on performance. This is because downloading, parsing, and running these scripts are done by main thread and this will block the execution of primary scripts. With more third-party scripts being used on a site, the application's performance will suffer greatly.

Async and Defer - Good Solution

Third-party script loading can be done while using Async and Defer. Async enables your script to begin working as soon as it has loaded, without interfering with other page components. Defer means that your script won't run until the page has completely loaded. Async and Defer are generally preferred, however there are several exceptions.

Partytown - Great Solution

From the documentation of Partytown-  

Partytown is a lazy-loaded library to help relocate resource intensive scripts into a web worker, and off of the main thread.

This library basically creates a webworker and runs the scripts behind the scenes to lighten the burden on the main thread.

How to integrate Partytown with Svelte app?

We can bootstrap a new svelte project using vite :  npm init vite




Install Partytown to your application : npm i @builder.io/partytown

Note that I have copied the necessary library files to the public folder using partytown copylib command : npx partytown copylib public/~partytown

Now add the partytown script inside head tag of index.html

<script src="/~partytown/partytown.js"></script>


In Svelte.config.ts file, add the following snippet.

const preprocess = require('svelte-preprocess');
module.exports = {
    preprocess: [
        preprocess({
            preserve: ['partytown'],
        }),
    ],
};

Finally add the partytownVite configuration under plugins in defineConfig of vite.confg.ts to instruct the vite to copy the library files during build.
import path from 'path';
import { partytownVite } from '@builder.io/partytown/utils';


export default defineConfig((...) => {
    return { ... ...
        build: {
....
            plugins: [
                partytownVite({
                    dest: path.join(__dirname, 'dist', '~partytown'),
                }),
            ],
        },
    };
});


Well done, now that partytown is integrated in your application. Any scripts that you want Partytown to process should be added to a head element. Just add the attribute type="text/partytown" to the script and place it there.

<script type="text/partytown" src="https://yourDomain.com/yourScript.js"></script>

Additional Configuration:
  • If you want to move Google Tag Manager Script to partytown, in addition to adding type attribute (text/partytown) to your GTM script, you need to add the following config in your index.html to forward all the datalayer events to webworker.
    <script>
                partytown = {
                    forward: ['dataLayer.push'],
                };
    </script>
  • When sending HTTP requests through a web worker, some third-party scripts have CORS problems. With Google Tag Manager, this is the situation and recommended solution is to use reverse proxy. Partytown provides resolveUrl method to map the proxy URL. An example for Google tag Manager is shown here.

    <script>
                partytown = {
                    forward: ['dataLayer.push'],
                    resolveUrl: (url) => {
                        const siteUrl = 'https://yourdomain.com/proxytown'
                        if (url.hostname === 'www.googletagmanager.com') {
                            const proxyUrl = new URL(`${siteUrl}/gtm`)
                            const gtmId = new URL(url).searchParams.get('id')
                            gtmId && proxyUrl.searchParams.append('id', gtmId)
                            return proxyUrl
                        }
                        return url
                    }
                }
    </script>
There we go! We have pushed GTM off the main thread! If you need any further information, please let me know in the comments.

Comments

Popular posts from this blog

Running Node.js Apps with dynamic NPM Packages in AWS Lambda

Impact of third-party scripts on Web applications.