Skip to content

Latest commit

Β 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

README.md

rspress-plugin-third-parties

rspress-plugin-third-parties banner

npm version npm downloads license React 19 Rspress Docs & Demo

High-performance third-party embeds, Google Tag Manager, analytics, and non-blocking script strategies for Rspress sites.

πŸ“– Read the Documentation Β· πŸš€ View Interactive Demo Β· πŸ“¦ NPM Package


⚑ Overview

rspress-plugin-third-parties brings Next.js-style third-party optimizations (@next/third-parties) directly to Rspress.

External embeds (like YouTube, Google Maps, and Twitter/X posts) and script tags (like GA4 and GTM) are notorious for blocking the main thread, lowering Lighthouse performance scores, and causing layout shifts. This plugin solves that by providing:

  • ⚑ React Compiler Pre-Optimized: Ships fully compiled with automated auto-memoization at build-time. Zero unnecessary re-renders.
  • πŸš€ Non-Blocking Execution: Lazy loading scripts using requestIdleCallback and fine-grained loading strategies.
  • ⚑ React 19 Resource Pre-initialization: Leverages native ReactDOM.preinit and ReactDOM.preload during SSG/SSR.
  • 🧠 Smart Memory Caching: Built-in script deduplication and stylesheet cache registry.
  • πŸ› οΈ Zero-Config Global GA: Inject Google Analytics across all documentation pages automatically via your rspress.config.ts.
  • πŸ“¦ Zero-Weight Embeds: Powered by third-party-capital for lightweight HTML generation.

πŸ“‘ Table of Contents


πŸ“¦ Installation

Install via your preferred package manager:

# pnpm
pnpm add rspress-plugin-third-parties

# npm
npm install rspress-plugin-third-parties

# yarn
yarn add rspress-plugin-third-parties

πŸ”Œ Plugin Registration

To auto-inject Google Analytics globally across your Rspress documentation, register the plugin in your rspress.config.ts:

// rspress.config.ts
import { defineConfig } from 'rspress/config';
import { pluginThirdParties } from 'rspress-plugin-third-parties/plugin';

export default defineConfig({
  plugins: [
    pluginThirdParties({
      googleAnalytics: {
        gaId: 'G-XXXXXXXXXX', // Your GA4 Measurement ID
        debugMode: false, // Set to true for local testing
        dataLayerName: 'dataLayer',
      },
    }),
  ],
});

🧩 Component Reference

<Script />

Source code

The foundation component powering all external integrations. It manages script mounting, deduplication, inline scripts, stylesheet preloading, and lifecycle events (onLoad, onReady, onError).

import { Script } from 'rspress-plugin-third-parties';

{/* Load after interactive */}

<Script
  src="https://sanjaiyan-cool.web.app/script/v1/1/SanWebMaker.js"
  strategy="afterInteractive"
  onLoad={() => console.log('Widgets loaded!')}
/>

{/* Inline Script */}
<Script id="custom-inline-script">
  {`console.log('Inline script running');`}
</Script>

<Script /> Props

Prop Type Default Description
src string "" Source URL of the script.
strategy "afterInteractive" | "lazyOnload" | "beforeInteractive" "afterInteractive" Script loading strategy.
id string src Unique script identifier used for cache deduplication.
onLoad (e: Event) => void β€” Callback fired when the script successfully loads.
onReady () => void β€” Callback fired on load, or immediately if script was previously loaded.
onError (e: Event) => void β€” Callback fired when script loading fails.
stylesheets string[] β€” Array of stylesheet URLs to pre-init/inject alongside the script.
nonce string β€” CSP nonce string.

<YouTubeEmbed />

Source code

Powered by lite-youtube-embed under the hood. Renders an ultra-fast visual facade that defers the heavy YouTube player until play is clickedβ€”keeping your main thread pristine and Lighthouse scores flawless.

import { YouTubeEmbed } from 'rspress-plugin-third-parties';

# Youtube Video

<YouTubeEmbed
  videoid="sSbDtQTtwBY"
  height={400}
  playlabel="A Lineage of Logic, A Future of Code"
/>

<YouTubeEmbed /> Props

Prop Type Default Description
videoid string Required The YouTube Video ID.
height number null Container height in pixels.
width number null Container width in pixels.
playlabel string 'Play' Accessible play button aria-label.
params string β€” Additional iframe URL parameters (e.g. "controls=0&start=10").
style string β€” Additional CSS styles for the container.

<GoogleMapsEmbed />

Source code

Provides performance-optimized embeds for Google Maps without blocking the browser during initial navigation.

import { GoogleMapsEmbed } from 'rspress-plugin-third-parties';

<GoogleMapsEmbed
  apiKey="YOUR_GOOGLE_MAPS_API_KEY"
  mode="place"
  q="Point Pedro, Sri Lanka"
  height={450}
  zoom="14"
/>

<GoogleMapsEmbed /> Props

Prop Type Default Description
apiKey string Required Your Google Maps Embed API key.
mode "place" | "view" | "directions" | "streetview" | "search" Required Embed mode.
q string β€” Map search query or location place name.
center string β€” Lat/lng center point ("9.814937,81.166080").
zoom string β€” Map zoom level (0 to 21).
maptype "roadmap" | "satellite" 'roadmap' Map rendering mode.
language string β€” Map language code (e.g. 'ta', 'en').
region string β€” Regional country code.
loading "eager" | "lazy" 'lazy' Native iframe loading attribute.

<TweetEmbed />

Source code

Zero-overhead Twitter/X post embed powered by react-tweet. Fetches raw post data and renders lightweight, native React DOM components styled identically to X/Twitter UI without downloading heavy widgets.js scripts or layout-shifting IFrames.

import { TweetEmbed } from 'rspress-plugin-third-parties';

{/* Basic Tweet */}

<TweetEmbed id="2017178323550605790" />

{/* Tweet with optional forced theme */}

<TweetEmbed id="2017178323550605790" theme="dark" />

<TweetEmbed /> Props

Prop Type Default Description
id string β€” The Tweet / X Post ID (extracted from tweet URL).
theme "light" | "dark" useDark() Optional theme override. Inherits Rspress reactive theme if omitted.
caption ReactNode β€” Optional accessible caption rendered in a <figcaption> tag beneath the tweet.
apiUrl string β€” Custom proxy API URL for fetching raw tweet data.
fallback ReactNode β€” Loading skeleton component rendered while tweet payload is being fetched.
components TwitterComponents β€” Custom UI component overrides for tweet elements (e.g. custom avatar, media, or links).
fetchOptions RequestInit β€” Custom fetch headers or request configuration sent to the tweet API.
onError (error: any) => any β€” Callback function fired if tweet data fetching or rendering fails.
className string β€” Additional CSS class names applied to the container <figure> element.

<GoogleAnalytics />

Source code

Explicitly embed Google Analytics 4 (GA4) inside MDX pages or custom layout components.

import { GoogleAnalytics } from 'rspress-plugin-third-parties';

<GoogleAnalytics gaId="G-XXXXXXXXXX" debugMode={true} />

<GoogleAnalytics /> Props

Prop Type Default Description
gaId string Required GA4 Measurement ID (G-XXXXXXXXXX).
dataLayerName string 'dataLayer' Custom global dataLayer array name.
debugMode boolean false Enables Google Analytics debug mode.
nonce string β€” CSP nonce string.

<GoogleTagManager />

Source code

Integrate Google Tag Manager (GTM) with support for custom domains, authentication, preview environments, and custom initial dataLayer states.

import { GoogleTagManager } from 'rspress-plugin-third-parties';

<GoogleTagManager
  gtmId="GTM-XXXXXXX"
  dataLayer={{ userRole: 'developer', env: 'production' }}
/>

<GoogleTagManager /> Props

Prop Type Default Description
gtmId string β€” GTM Container ID (GTM-XXXXXXX).
gtmScriptUrl string 'https://www.googletagmanager.com/gtm.js' Custom domain proxy URL for GTM script.
dataLayer Record<string, JSONValue> β€” Initial dataLayer object payload.
dataLayerName string 'dataLayer' Custom dataLayer global array name.
auth string β€” GTM Environment authentication string (gtm_auth).
preview string β€” GTM Environment preview string (gtm_preview).
nonce string β€” CSP nonce string.

Note

You must provide either gtmId or a custom gtmScriptUrl containing the ID parameter.


πŸ“Š Event Tracking Utility

Send custom Google Analytics events dynamically from anywhere in your client-side React code:

import { sendGAEvent } from 'rspress-plugin-third-parties';

function FeedbackButton() {
  const handleClick = () => {
    sendGAEvent('event', 'documentation_helpful', {
      page: window.location.pathname,
      vote: 'yes',
    });
  };

  return <button onClick={handleClick}>Helpful πŸ‘</button>;
}

🎯 Script Loading Strategies

Strategy Timing Ideal For
afterInteractive (Default) Injected immediately after page hydration. Analytics, Tag Managers, essential widgets.
lazyOnload Injected during browser idle time (requestIdleCallback). Chat widgets, social feeds, low-priority pixels.
beforeInteractive Rendered into raw HTML prior to client JS execution during SSG. Critical consent scripts, anti-bot security.

πŸ”¬ Under the Hood Mechanics

                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚          Rspress SSG Build Phase        β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚      Server Pre-render Execution        β”‚
                  β”‚   Calls safePreload() & safePreinit()   β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
                                       β–Ό
                     HTML Output with Native Preloads
                                       β”‚
                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                  β”‚        Hydration & Browser Idle         β”‚
                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                       β”‚
             β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
             β”‚                         β”‚                         β”‚
             β–Ό                         β–Ό                         β–Ό
   [afterInteractive]           [lazyOnload]           [Cache Deduplication]
   Appends script after     Uses requestIdleCallback     Prevents fetching identical
   client hydration.        to minimize TBT.             `src`/`id` entries twice.
  1. React 19 Resource Pre-init: Uses ReactDOM.preinit and ReactDOM.preload to declare external resource hints before browser parsing.
  2. Script Caching: Maintains global ScriptCache and LoadCache Map/Set singletons, ensuring identical script tags are never loaded twice across page transitions.
  3. Graceful React 18 Fallback: Fallbacks to dynamic document.createElement('link') stylesheet injection when React 19 resource pre-init functions are unavailable.

Development

Run these commands from the monorepo root:

pnpm install
pnpm --filter rspress-plugin-third-parties build
pnpm exec playwright install chromium
pnpm e2e rspress-plugin-third-parties
pnpm lint
pnpm --filter rspress-plugin-third-parties docs:build
pnpm --filter rspress-plugin-third-parties docs:dev

The package uses the shared Rstack toolchain, TypeScript configuration, and pnpm catalog. It publishes ESM components and a separate Node.js plugin entry. Playwright tests run alongside the other plugins through the root pnpm e2e command. Versioning and publishing use the root Changesets configuration.

πŸ“„ License

MIT Β© Sanjaiyan Parthipan and the Rspress Community (from September 2026 onward)