Using Partytown to load third-party scripts in SolidStart
Partytown provides a novel approach to load third-party scripts such as analytics in the background using web workers. This offloads non-essential scripts off the main thread speeding up your web app. This does not come without trade-offs though.
Getting Started
Create a new SolidStart project.
pnpm create solid
Install Partytown.
pnpm install @builder.io/partytown
Configuring Partytown
We need to serve Partytown’s scripts. Partytown provides a Vite plugin to copy files to our public folder serve them during development from Vite’s dev server, however I ran into issues with this approach with some deployment presets. A Nitro module similar to @nuxtjs/partytown
would probably be ideal.
import { partytownVite } from "@builder.io/partytown/utils"import { defineConfig } from "@solidjs/start/config"import path from "path"
export default defineConfig({ plugins: [ partytownVite({ // The absolute path to your build output public directory dest: path.join(__dirname, ".output/public", "~partytown"), }), ],})
Instead of the Vite plugin, I opted for the low tech approach. I added a script to my package.json
to copy the files during build step. Be sure to run the script once locally to generate the files in development.
{ "scripts": { "build": "pnpm run partytown && vinxi build", "partytown": "partytown copylib public/~partytown" }}
Additionally I added the Partytown folder to my .gitignore
so it is not committed to my repo.
# Partytownpublic/~partytown
You can run pnpm run build
to build your project and see the Partytown scripts in your public folder, .output/public/~partytown
.
Next we need to load Partytown’s scripts in our app. To do this we can use <Assets>
from Solid to add the scripts to our head.
With Partytown, setting a <script>
type to "text/partytown"
will tell Partytown to run the script.
import { partytownSnippet } from "@builder.io/partytown/integration"import { Assets } from "solid-js/web"
export default function App() { return ( <Router root={(props) => ( <> {/* Partytown scripts */} <Assets> <script>{partytownSnippet()}</script> <script type="text/partytown">{"console.log('Hello from Partytown!')"}</script> </Assets>
<Nav /> <Suspense>{props.children}</Suspense> </> )} > <FileRoutes /> </Router> )}
You should see “Hello from Partytown!” in your console.
Using Partytown
Now that we have Partytown setup we can use it to run our code in a web worker. A common usecase for this is for analytics. Here is an example using Google Analytics with forwarding events.
<Assets> <script>{partytownSnippet()}</script> <script type="text/partytown">{`partytown = { forward: ['gtag', 'dataLayer.push'] }`}</script> <script type="text/partytown" src="https://www.googletagmanager.com/gtag/js?id=YOUR-ID-HERE"></script> <script type="text/partytown"> {`window.dataLayer = window.dataLayer || []; window.gtag = function () { dataLayer.push(arguments); }; window.gtag('js', new Date());
window. gtag('config', 'YOUR-ID-HERE');`} </script></Assets>
Inspect your chrome network tab and you should see the Google Analytics script being loaded from Partytown service worker as well as requests being forwarded via proxytown.
