npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vite-plugin-smart-prefetch

v0.3.3

Published

Smart prefetch plugin for Vite with BigQuery GA4 analytics. Supports React Router DOM and TanStack Router with intelligent dynamic route matching.

Readme

@farmart/vite-plugin-smart-prefetch

Smart prefetch plugin for Vite applications powered by BigQuery GA4 analytics

Automatically prefetch route chunks based on real user navigation patterns from BigQuery GA4 export. Improve perceived performance by up to 80-90% for predicted route transitions.

Features

  • 🤖 Smart Learning - Analyzes BigQuery GA4 event data to learn user navigation patterns
  • 📊 Data-Driven - Prefetch decisions based on actual user behavior, not assumptions
  • Multiple Strategies - Auto, hover, visible, idle, or hybrid prefetching
  • 🌐 Network-Aware - Respects data-saver mode and connection quality
  • 💾 Smart Caching - Caches computed models with TTL for efficiency
  • 🎯 Framework Support - React (Vue and Svelte coming soon)
  • 🔧 Zero Config - Works out of the box with sensible defaults
  • 📈 Environment-Specific - Different models for production, staging, development

Installation

# Using pnpm (recommended for monorepos)
pnpm add @farmart/vite-plugin-smart-prefetch

# Using npm
npm install @farmart/vite-plugin-smart-prefetch

# Using yarn
yarn add @farmart/vite-plugin-smart-prefetch

Quick Start

1. Setup BigQuery for GA4 Export

# 1. Enable BigQuery export from GA4 Console
# GA4 Admin > Data Export > BigQuery

# 2. Create Google Cloud service account
# https://console.cloud.google.com/iam-admin/serviceaccounts

# 3. Grant "BigQuery Data Viewer" and "BigQuery Job User" roles

# 4. Create and download JSON key
# Service Accounts > Keys > Add Key > Create New Key > JSON

# 5. Add to environment variables

.env:

VITE_GA_PROPERTY_ID=123456789
VITE_GA_CLIENT_EMAIL=prefetch@your-project.iam.gserviceaccount.com
VITE_GA_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"

2. Configure Vite Plugin

vite.config.mts:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { smartPrefetch } from '@farmart/vite-plugin-smart-prefetch';

export default defineConfig({
  plugins: [
    react(),
    smartPrefetch({
      framework: 'react',
      strategy: 'hybrid',
      analytics: {
        provider: 'google-analytics',
        credentials: {
          propertyId: process.env.VITE_GA_PROPERTY_ID!,
          clientEmail: process.env.VITE_GA_CLIENT_EMAIL!,
          privateKey: process.env.VITE_GA_PRIVATE_KEY!,
        },
        dataRange: {
          days: 30,           // Analyze last 30 days
          minSessions: 100,   // Minimum sessions threshold
        },
        model: {
          type: 'probability',
          threshold: 0.3,     // 30% probability threshold
          maxPrefetch: 3,     // Max 3 routes per page
        },
        environment: process.env.NODE_ENV || 'production',
      },
      manualRules: {
        // Optional: Override ML predictions
        '/checkout': ['/payment'],
      },
      cache: {
        enabled: true,
        ttl: 24 * 60 * 60 * 1000, // 24 hours
      },
    }),
  ],
});

3. Add to Your App

App.tsx:

import { usePrefetch } from '@farmart/vite-plugin-smart-prefetch/react';

function App() {
  // That's it! Plugin handles everything
  usePrefetch();

  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/orders" element={<Orders />} />
      <Route path="/dispatch-order" element={<DispatchOrder />} />
    </Routes>
  );
}

4. Build & Deploy

npm run build

The plugin will:

  1. ✅ Connect to Google Analytics
  2. ✅ Fetch navigation data
  3. ✅ Train probability model
  4. ✅ Generate prefetch-config.json
  5. ✅ Cache model for future builds

Configuration

Plugin Options

interface PluginOptions {
  /** Framework (default: 'react') */
  framework?: 'react' | 'vue' | 'svelte';

  /** Prefetch strategy (default: 'hybrid') */
  strategy?: 'auto' | 'hover' | 'visible' | 'idle' | 'hybrid';

  /** Google Analytics integration */
  analytics?: AnalyticsConfig;

  /** Manual prefetch rules */
  manualRules?: {
    [sourceRoute: string]: string[];
  };

  /** Cache configuration */
  cache?: {
    enabled?: boolean;
    ttl?: number;
    path?: string;
  };

  /** Advanced options */
  advanced?: {
    debug?: boolean;
    excludeRoutes?: string[];
  };
}

Prefetch Strategies

| Strategy | Description | Use Case | |----------|-------------|----------| | auto | Prefetch immediately on route change | High-confidence predictions | | hover | Prefetch when user hovers over link | User intent signals | | visible | Prefetch when link becomes visible | Below-the-fold content | | idle | Prefetch during browser idle time | Low priority routes | | hybrid | Smart combination based on probability | Recommended |

Hybrid Strategy (Recommended)

  • High priority (>70% probability): Prefetch immediately
  • Medium priority (40-70%): Prefetch on idle
  • Low priority (30-40%): Prefetch on hover/visible

React Integration

usePrefetch Hook

import { usePrefetch } from '@farmart/vite-plugin-smart-prefetch/react';

function App() {
  // Automatically prefetches routes based on navigation
  usePrefetch();

  return <Routes>...</Routes>;
}

PrefetchLink Component

Enhanced Link component with manual control:

import { PrefetchLink } from '@farmart/vite-plugin-smart-prefetch/react';

// Prefetch on hover
<PrefetchLink to="/orders" prefetch="hover">
  View Orders
</PrefetchLink>

// Prefetch when visible (great for lists)
<PrefetchLink to="/dispatch-order" prefetch="visible">
  Create Dispatch
</PrefetchLink>

// Manual control (no automatic prefetch)
<PrefetchLink to="/settings" prefetch="manual">
  Settings
</PrefetchLink>

Manual Prefetch Control

import { getPrefetchManager } from '@farmart/vite-plugin-smart-prefetch/react';

function MyComponent() {
  const handleMouseEnter = () => {
    const manager = getPrefetchManager();
    manager?.prefetchRoute('/orders');
  };

  return (
    <button onMouseEnter={handleMouseEnter}>
      View Orders
    </button>
  );
}

How It Works

Build Time

1. Connect to Google Analytics
   ├── Authenticate with service account
   └── Fetch last 30 days of navigation data

2. Train Model
   ├── Calculate transition probabilities
   │   Example: P(/dispatch-order | /orders) = 0.58
   ├── Apply threshold filter (>30%)
   └── Select top 3 predictions per route

3. Generate Configuration
   ├── Map routes to Vite chunks
   │   /dispatch-order → assets/dispatch-order-abc123.js
   └── Emit prefetch-config.json

4. Cache Model
   ├── Save to node_modules/.cache/smart-prefetch/
   └── TTL: 24 hours (configurable)

Runtime

1. App Loads
   ├── usePrefetch() initializes
   └── Fetch /prefetch-config.json

2. User on /orders page
   ├── Check network conditions (Data Saver, 2G, etc.)
   ├── Read predictions: [/dispatch-order (58%), /orders/:id (42%)]
   └── Apply strategy:
       - High priority: Prefetch immediately
       - Medium: Prefetch on idle
       - Low: Wait for hover/visible

3. Inject <link rel="prefetch">
   <link rel="prefetch" href="/assets/dispatch-order-abc123.js">

4. User clicks "Dispatch Order"
   ├── Chunk already in browser cache!
   └── Load time: ~10ms instead of ~300ms

Performance Impact

Before vs After

| Metric | Without Prefetch | With Prefetch | Improvement | |--------|------------------|---------------|-------------| | Route transition | 250-500ms | 10-50ms | 80-90% faster | | Cache hit rate | 0% | 60-80% | New capability | | Time to Interactive | Baseline | -15-20% | Faster |

Real-World Example

Example: /orders → /dispatch-order (58% probability)

Without prefetch:
  1. User clicks link
  2. Download dispatch-order-abc123.js (300ms)
  3. Parse and execute (50ms)
  Total: 350ms

With prefetch:
  1. User lands on /orders
  2. Plugin prefetches dispatch-order-abc123.js in background
  3. User clicks link
  4. Load from cache (5ms)
  5. Parse and execute (50ms)
  Total: 55ms (84% faster!)

Network-Aware Prefetching

The plugin automatically detects and respects:

  • Data Saver mode - No prefetch if enabled
  • Slow connections - No prefetch on 2G/slow-2G
  • Metered connections - Conservative prefetch on cellular
  • Connection quality - Uses Network Information API
// Automatic detection (no configuration needed)
if (navigator.connection.saveData) {
  // Skip prefetch
}

if (connection.effectiveType === '2g') {
  // Skip prefetch
}

Cache Management

Cache Location

node_modules/.cache/smart-prefetch/
├── model-production.json    # Production model
├── model-staging.json        # Staging model
└── metadata.json             # Cache metadata

Invalidate Cache

# Invalidate all cache
rm -rf node_modules/.cache/smart-prefetch

# Or programmatically
const cacheManager = new CacheManager();
await cacheManager.invalidate();

Cache Stats

const stats = cacheManager.getStats();
// {
//   enabled: true,
//   cacheDir: './node_modules/.cache/smart-prefetch',
//   ttl: 86400000,
//   cachedEnvironments: ['production', 'staging'],
//   totalSize: 45678
// }

Manual Rules

Override ML predictions with manual rules:

smartPrefetch({
  manualRules: {
    // Always prefetch payment on checkout
    '/checkout': ['/payment'],

    // Multiple targets
    '/': ['/products', '/orders', '/dashboard'],

    // Dynamic routes (use :id notation)
    '/orders/:id': ['/dispatch-order/:id'],
  },
})

Manual rules:

  • ✅ Take precedence over ML predictions
  • ✅ Always have priority: 'high'
  • ✅ Always have probability: 1.0
  • ✅ Merged with analytics data

Debugging

Enable debug mode to see detailed logs:

smartPrefetch({
  advanced: {
    debug: true,
  },
})

Build-Time Logs

🚀 Smart Prefetch Plugin Initialized
   Framework: react
   Strategy: hybrid
   Analytics: enabled

📊 Fetching analytics data...
   Date range: Last 30 days
   Min sessions threshold: 100

✅ Fetched 87 navigation patterns

🤖 Training prefetch model...
   Model type: probability
   Threshold: 30%
   Max prefetch per route: 3

✅ Model trained successfully
   Routes with predictions: 42

📦 Generating prefetch configuration...
   Manifest entries: 156
   Mapped chunks: 89

Runtime Logs

🚀 Prefetch Manager Initialized
   Strategy: hybrid
   Routes: 42
   Environment: production

📦 Prefetching for route: /orders
   Targets: 2
   ✅ Prefetched: /dispatch-order (58%, high)
   ✅ Prefetched: /orders/:id (42%, medium)

Troubleshooting

Issue: "Failed to load prefetch config"

Solution: Ensure /prefetch-config.json is in your build output (dist/).

# Check if file exists
ls dist/prefetch-config.json

Issue: "Google Analytics connection test failed"

Solutions:

  1. Verify service account has "Viewer" access to GA4 property
  2. Check credentials in .env file
  3. Ensure private key has correct newlines (\n)
# Test credentials
echo $VITE_GA_PRIVATE_KEY | grep "BEGIN PRIVATE KEY"

Issue: "No navigation data found"

Solutions:

  1. Ensure GA4 property has at least 30 days of data
  2. Lower minSessions threshold
  3. Check GA4 property ID is correct

Issue: "No chunk found for route"

Solution: Adjust route normalization or use manual rules:

smartPrefetch({
  manualRules: {
    '/my-route': ['/target-route'],
  },
  advanced: {
    routeNormalization: (path) => {
      // Custom normalization logic
      return path.replace(/\/[0-9]+/g, '/:id');
    },
  },
})

Best Practices

1. Use Hybrid Strategy

strategy: 'hybrid'  // ✅ Recommended

Automatically prioritizes prefetch based on prediction confidence.

2. Set Appropriate Thresholds

model: {
  threshold: 0.3,      // 30% - Good balance
  maxPrefetch: 3,      // Limit bandwidth usage
}
  • Too low (<20%): Wastes bandwidth
  • Too high (>50%): Misses opportunities

3. Use Manual Rules for Critical Paths

manualRules: {
  '/checkout': ['/payment'],  // Always prefetch payment
}

4. Monitor Prefetch Performance

Enable dashboard to visualize predictions:

analytics: {
  dashboard: true,  // Generates prefetch-report.html
}

Access at: https://your-app.com/prefetch-report.html

5. Environment-Specific Models

// Production
environment: 'production'

// Staging
environment: 'staging'

Keeps models separate for different user behaviors.


API Reference

See RFC-001-SMART-PREFETCH-PLUGIN.md for detailed API documentation.


Contributing

This is an internal FarmArt Engineering package. For issues or feature requests, please contact the engineering team.


License

MIT © FarmArt Engineering


Support

For questions or support:

  • Internal Slack: #engineering
  • Documentation: See RFC-001 in project root
  • Issues: Create ticket in project management tool