Smart prefetch plugin for Vite with BigQuery GA4 analytics. Supports React Router DOM and TanStack Router with intelligent dynamic route matching.
npm install vite-plugin-smart-prefetchSmart 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.
- š¤ 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
---
``bashUsing pnpm (recommended for monorepos)
pnpm add @farmart/vite-plugin-smart-prefetch
---
Quick Start
$3
`bash
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:
`bash
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"
`$3
vite.config.mts:
`typescript
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
App.tsx:
`typescript
import { usePrefetch } from '@farmart/vite-plugin-smart-prefetch/react';function App() {
// That's it! Plugin handles everything
usePrefetch();
return (
} />
} />
} />
);
}
`$3
`bash
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
$3
`typescript
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[];
};
}
`$3
| 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
$3
`typescript
import { usePrefetch } from '@farmart/vite-plugin-smart-prefetch/react';function App() {
// Automatically prefetches routes based on navigation
usePrefetch();
return ... ;
}
`$3
Enhanced
Link component with manual control:`tsx
import { PrefetchLink } from '@farmart/vite-plugin-smart-prefetch/react';// Prefetch on hover
View Orders
// Prefetch when visible (great for lists)
Create Dispatch
// Manual control (no automatic prefetch)
Settings
`$3
`typescript
import { getPrefetchManager } from '@farmart/vite-plugin-smart-prefetch/react';function MyComponent() {
const handleMouseEnter = () => {
const manager = getPrefetchManager();
manager?.prefetchRoute('/orders');
};
return (
);
}
`---
How It Works
$3
`
1. Connect to Google Analytics
āāā Authenticate with service account
āāā Fetch last 30 days of navigation data2. 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)
`$3
`
1. App Loads
āāā usePrefetch() initializes
āāā Fetch /prefetch-config.json2. 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
4. User clicks "Dispatch Order"
āāā Chunk already in browser cache!
āāā Load time: ~10ms instead of ~300ms
`---
Performance Impact
$3
| 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 |
$3
`
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
`typescript
// Automatic detection (no configuration needed)
if (navigator.connection.saveData) {
// Skip prefetch
}if (connection.effectiveType === '2g') {
// Skip prefetch
}
`---
Cache Management
$3
`
node_modules/.cache/smart-prefetch/
āāā model-production.json # Production model
āāā model-staging.json # Staging model
āāā metadata.json # Cache metadata
`$3
`bash
Invalidate all cache
rm -rf node_modules/.cache/smart-prefetchOr programmatically
const cacheManager = new CacheManager();
await cacheManager.invalidate();
`$3
`typescript
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:
`typescript
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:
`typescript
smartPrefetch({
advanced: {
debug: true,
},
})
`$3
`
š 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
`$3
`
š 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
$3
Solution: Ensure
/prefetch-config.json is in your build output (dist/).`bash
Check if file exists
ls dist/prefetch-config.json
`$3
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)`bash
Test credentials
echo $VITE_GA_PRIVATE_KEY | grep "BEGIN PRIVATE KEY"
`$3
Solutions:
1. Ensure GA4 property has at least 30 days of data
2. Lower
minSessions threshold
3. Check GA4 property ID is correct$3
Solution: Adjust route normalization or use manual rules:
`typescript
smartPrefetch({
manualRules: {
'/my-route': ['/target-route'],
},
advanced: {
routeNormalization: (path) => {
// Custom normalization logic
return path.replace(/\/[0-9]+/g, '/:id');
},
},
})
`---
Best Practices
$3
`typescript
strategy: 'hybrid' // ā
Recommended
`Automatically prioritizes prefetch based on prediction confidence.
$3
`typescript
model: {
threshold: 0.3, // 30% - Good balance
maxPrefetch: 3, // Limit bandwidth usage
}
`- Too low (<20%): Wastes bandwidth
- Too high (>50%): Misses opportunities
$3
`typescript
manualRules: {
'/checkout': ['/payment'], // Always prefetch payment
}
`$3
Enable dashboard to visualize predictions:
`typescript
analytics: {
dashboard: true, // Generates prefetch-report.html
}
`Access at:
https://your-app.com/prefetch-report.html$3
`typescript
// 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`