You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Third-party capital was being used previously to generate some of the static data needed for a subset of the registry scripts (youtube, google maps, google analytics, google tag manager).
The runtime dependency has since been removed in a PR for several reasons below. We still use the exported types for the scripts.
Runtime Overhead
Third-party-capital has quite a hefty runtime bundle size relatively. Consider that the useScript wrapper from Unhead and Nuxt itself is only around ~2kb, which I think is too high and would be exploring further ways to bring it down. For Nuxt Scripts to be maximally useful it needs to be as minimal as possible.
The minified bundled size for each export with comparisons for current size:
Google Analytics: 1.7KB (vs 393B)
Google Tag Manager 1.6KB (vs 384B)
Google Maps 1.6KB minified (n/a as the implementation is different to TPC)
Youtube 1.7KB minified (n/a as the implementation is different to TPC)
Convulated implementation / no implementation types
TPC abstracts away the implementation details inside of a JSON file that has custom parsing, this makes it quite difficult to debug the behaviour of the code without digging into the entire code base implementation.
import{GoogleAnalytics}from'third-party-capital'constschema=GoogleAnalytics({/* options */)// schema is generically typedconstscripts=schema.scripts// scripts is an array, no way to know which script is the load of the script verse the bootstrap setup
Because the implementation is not obvious, it adds a disconnect between how the the use() and the stubs are implemented versus the rest of the script.
For example for SSR in GTM, we need to stub dataLayer as an array so we can push to it.
scriptOptions: {use(){return{dataLayer: window.dataLayer,google_tag_manager: window.google_tag_manager}},// allow dataLayer to be accessed on the serverstub: import.meta.client
? undefined
: ({ fn })=>{returnfn==='dataLayer' ? [] : undefined},},
Leveraging Nuxt Tree Shaking for Micro-Optimizations
Since Nuxt is a SSR framework, there are certain optimizations we can opt-in to that environment agnostic packages can't, as they have no control over the SSR lifecycle.
if(import.meta.server){// offload logic to the server instead of having the client do it// - gets treeshaken out of the client-build}
A simple example of a micro-optimization is not passing any code that only the client needs to use. For example, we need to bootstrap the window for most third-party scripts, in Nuxt we can easily leverage tree-shaking to make sure this code isn't in the server bundle.
// packages publish code like this to be environment agnosticif(typeofwindow!=='undefined'){}
// in nuxt we can just treeshake as we have control over rollupif(import.meta.client){window.myLib={}}
For something concrete, we can consider not running head injection tasks on the client when we can just do it on the server, reducing the time to hydrate the client.
We can see this in the ScriptYouTubePlayer component.
if(import.meta.server){useHead({link: [{rel: props.aboveTheFold ? 'preconnect' : 'dns-prefetch',href: 'https://i.ytimg.com',},props.aboveTheFold// we can preload the placeholder image
? {rel: 'preload',as: 'image',href: placeholder.value,}
: {},],})}
To achieve this with TPC would be quite difficult and would unlikely to work even if we can tree shake.
Maintanence DX
Nuxt Scripts is providing out-of-the-box support for 16 scripts, having 4 of them being configured differently through an external dependency we don't have control over will make maintenance harder in the short and long term.
I'd also like to see the repo more active generally, the following remain open and unanswered.
I think the way of integrating TPC into nuxt-scripts is to do it at build-time. Not at nuxt-script bundle-time but at users build-time by having TPC as a peerdep and external within nuxt scripts.
The idea is to have TPC kept as external but still added in the registry.
It will be up to users to update TPC to have the latest version.
We could also check TPC version within nuxt-script module setup time and warn the user that a new version of TPC is available.
Background
Third-party capital was being used previously to generate some of the static data needed for a subset of the registry scripts (youtube, google maps, google analytics, google tag manager).
The runtime dependency has since been removed in a PR for several reasons below. We still use the exported types for the scripts.
Runtime Overhead
Third-party-capital has quite a hefty runtime bundle size relatively. Consider that the
useScript
wrapper from Unhead and Nuxt itself is only around ~2kb, which I think is too high and would be exploring further ways to bring it down. For Nuxt Scripts to be maximally useful it needs to be as minimal as possible.The minified bundled size for each export with comparisons for current size:
Convulated implementation / no implementation types
TPC abstracts away the implementation details inside of a JSON file that has custom parsing, this makes it quite difficult to debug the behaviour of the code without digging into the entire code base implementation.
Because the implementation is not obvious, it adds a disconnect between how the the
use()
and the stubs are implemented versus the rest of the script.For example for SSR in GTM, we need to stub dataLayer as an array so we can push to it.
Leveraging Nuxt Tree Shaking for Micro-Optimizations
Since Nuxt is a SSR framework, there are certain optimizations we can opt-in to that environment agnostic packages can't, as they have no control over the SSR lifecycle.
A simple example of a micro-optimization is not passing any code that only the client needs to use. For example, we need to bootstrap the
window
for most third-party scripts, in Nuxt we can easily leverage tree-shaking to make sure this code isn't in the server bundle.For something concrete, we can consider not running head injection tasks on the client when we can just do it on the server, reducing the time to hydrate the client.
We can see this in the
ScriptYouTubePlayer
component.To achieve this with TPC would be quite difficult and would unlikely to work even if we can tree shake.
Maintanence DX
Nuxt Scripts is providing out-of-the-box support for 16 scripts, having 4 of them being configured differently through an external dependency we don't have control over will make maintenance harder in the short and long term.
I'd also like to see the repo more active generally, the following remain open and unanswered.
Reimplementing TPC
I'm happy to reconsider adding TPC within the runtime if the above can be solved or some other value can be provided that justifies the constraints.
The text was updated successfully, but these errors were encountered: