vite-plugin-smart-prefetch 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +23 -191
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -19
- package/dist/index.d.ts +2 -19
- package/dist/index.js +23 -191
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +70 -211
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +112 -127
- package/dist/react/index.d.ts +112 -127
- package/dist/react/index.js +55 -181
- package/dist/react/index.js.map +1 -1
- package/dist/runtime/index.cjs +35 -35
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +30 -25
- package/dist/runtime/index.d.ts +30 -25
- package/dist/runtime/index.js +35 -35
- package/dist/runtime/index.js.map +1 -1
- package/package.json +4 -8
package/dist/react/index.d.ts
CHANGED
|
@@ -1,8 +1,88 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { LinkProps } from 'react-router-dom';
|
|
3
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
2
|
|
|
5
3
|
type PrefetchStrategy = 'auto' | 'hover' | 'visible' | 'idle' | 'hybrid';
|
|
4
|
+
interface ModelConfig {
|
|
5
|
+
/** Model type */
|
|
6
|
+
type: 'probability' | 'ml' | 'hybrid';
|
|
7
|
+
/** Minimum probability threshold (0.0 - 1.0, default: 0.3) */
|
|
8
|
+
threshold: number;
|
|
9
|
+
/** Maximum routes to prefetch per page (default: 3) */
|
|
10
|
+
maxPrefetch: number;
|
|
11
|
+
/** How often to update the model */
|
|
12
|
+
updateInterval?: 'build' | 'daily' | 'weekly';
|
|
13
|
+
}
|
|
14
|
+
interface DataSourceMetadata {
|
|
15
|
+
/** Provider name */
|
|
16
|
+
provider: 'bigquery' | 'markov-chain' | 'manual' | string;
|
|
17
|
+
/** Date range analyzed */
|
|
18
|
+
dateRange: string;
|
|
19
|
+
/** Total sessions analyzed */
|
|
20
|
+
totalSessions: number;
|
|
21
|
+
/** Total unique routes found */
|
|
22
|
+
totalRoutes?: number;
|
|
23
|
+
}
|
|
24
|
+
interface PrefetchTarget {
|
|
25
|
+
/** Target route to prefetch */
|
|
26
|
+
route: string;
|
|
27
|
+
/** Probability of transition (0.0 - 1.0) */
|
|
28
|
+
probability: number;
|
|
29
|
+
/** Number of observed transitions */
|
|
30
|
+
count: number;
|
|
31
|
+
/** Chunk file to prefetch (set by config generator) */
|
|
32
|
+
chunk?: string;
|
|
33
|
+
/** Production chunk file path (for production builds) */
|
|
34
|
+
chunk_prod?: string;
|
|
35
|
+
/** Dependency chunks to prefetch (extracted from Vite manifest imports) */
|
|
36
|
+
imports?: string[];
|
|
37
|
+
/** Priority level */
|
|
38
|
+
priority: 'high' | 'medium' | 'low';
|
|
39
|
+
/** Whether this is a manual rule */
|
|
40
|
+
manual?: boolean;
|
|
41
|
+
}
|
|
42
|
+
interface RouteMetadata {
|
|
43
|
+
/** Total transitions from this route */
|
|
44
|
+
totalTransitions: number;
|
|
45
|
+
/** Most common destination */
|
|
46
|
+
topDestination: string;
|
|
47
|
+
/** Average time spent on page (seconds) */
|
|
48
|
+
averageTimeOnPage?: number;
|
|
49
|
+
}
|
|
50
|
+
interface PrefetchConfig {
|
|
51
|
+
/** Schema version */
|
|
52
|
+
version: string;
|
|
53
|
+
/** Generation timestamp */
|
|
54
|
+
generatedAt: string;
|
|
55
|
+
/** Environment */
|
|
56
|
+
environment: string;
|
|
57
|
+
/** Data source info */
|
|
58
|
+
dataSource: DataSourceMetadata;
|
|
59
|
+
/** Model info */
|
|
60
|
+
model: {
|
|
61
|
+
type: ModelConfig['type'];
|
|
62
|
+
threshold: number;
|
|
63
|
+
maxPrefetch: number;
|
|
64
|
+
accuracy?: number;
|
|
65
|
+
};
|
|
66
|
+
/** Global route patterns for dynamic route matching */
|
|
67
|
+
routePatterns?: Record<string, string[]>;
|
|
68
|
+
/** Route predictions with chunk mappings */
|
|
69
|
+
routes: {
|
|
70
|
+
[sourceRoute: string]: {
|
|
71
|
+
/** Route pattern variants (for matching dynamic routes like /order/:id) */
|
|
72
|
+
patterns?: string[];
|
|
73
|
+
/** Prefetch rules for this route */
|
|
74
|
+
prefetch: Array<PrefetchTarget & {
|
|
75
|
+
chunk: string;
|
|
76
|
+
}>;
|
|
77
|
+
/** Metadata about this route */
|
|
78
|
+
metadata?: RouteMetadata;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** Quick lookup: route -> chunk file */
|
|
82
|
+
chunks: {
|
|
83
|
+
[route: string]: string;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
6
86
|
|
|
7
87
|
/**
|
|
8
88
|
* Prefetch Manager (Runtime)
|
|
@@ -15,24 +95,19 @@ declare class PrefetchManager {
|
|
|
15
95
|
private strategy;
|
|
16
96
|
private observer;
|
|
17
97
|
private debug;
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
|
|
98
|
+
private currentLocation;
|
|
99
|
+
/**
|
|
100
|
+
* Constructor
|
|
101
|
+
* @param strategy Prefetch strategy: 'auto', 'hover', 'visible', 'idle', or 'hybrid'
|
|
102
|
+
* @param debug Enable debug logging
|
|
103
|
+
* @param initialLocation Optional initial location (pathname)
|
|
104
|
+
*/
|
|
105
|
+
constructor(strategy?: PrefetchStrategy, debug?: boolean, initialLocation?: string);
|
|
21
106
|
/**
|
|
22
107
|
* Initialize the prefetch manager
|
|
23
108
|
* Loads configuration and sets up observers
|
|
24
109
|
*/
|
|
25
110
|
init(): Promise<void>;
|
|
26
|
-
/**
|
|
27
|
-
* Set the user segment for segment-based prefetch rules
|
|
28
|
-
* @param segment - The user's segment (e.g., 'premium', 'free', 'admin')
|
|
29
|
-
* @param fallbackToDefault - Use default rules if segment rules unavailable
|
|
30
|
-
*/
|
|
31
|
-
setSegment(segment: string | null, fallbackToDefault?: boolean): void;
|
|
32
|
-
/**
|
|
33
|
-
* Get the current segment
|
|
34
|
-
*/
|
|
35
|
-
getSegment(): string | null;
|
|
36
111
|
/**
|
|
37
112
|
* Match pathname against a route pattern
|
|
38
113
|
* Supports both React Router (:id) and TanStack Router ($id) syntax
|
|
@@ -42,6 +117,27 @@ declare class PrefetchManager {
|
|
|
42
117
|
* matchRoutePattern('/admin/settings', '/admin/*') → true
|
|
43
118
|
*/
|
|
44
119
|
private matchRoutePattern;
|
|
120
|
+
/**
|
|
121
|
+
* Update current location and trigger prefetch
|
|
122
|
+
* Call this whenever the application's location changes
|
|
123
|
+
*
|
|
124
|
+
* @param pathname The current pathname (can be from location.pathname, useLocation().pathname, etc.)
|
|
125
|
+
* @example
|
|
126
|
+
* ```tsx
|
|
127
|
+
* // In React Router DOM
|
|
128
|
+
* const location = useLocation();
|
|
129
|
+
* useEffect(() => {
|
|
130
|
+
* manager.onLocationChange(location.pathname);
|
|
131
|
+
* }, [location.pathname]);
|
|
132
|
+
*
|
|
133
|
+
* // In TanStack Router
|
|
134
|
+
* const location = useLocation();
|
|
135
|
+
* useEffect(() => {
|
|
136
|
+
* manager.onLocationChange(location.pathname);
|
|
137
|
+
* }, [location.pathname]);
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
onLocationChange(pathname: string): void;
|
|
45
141
|
/**
|
|
46
142
|
* Prefetch routes based on current route
|
|
47
143
|
*/
|
|
@@ -117,117 +213,6 @@ declare class PrefetchManager {
|
|
|
117
213
|
logPrefetchSummary(): void;
|
|
118
214
|
}
|
|
119
215
|
|
|
120
|
-
/**
|
|
121
|
-
* React Hook for Smart Prefetch
|
|
122
|
-
* Automatically prefetches routes based on navigation
|
|
123
|
-
*/
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* React hook to enable smart prefetching
|
|
127
|
-
* Call this once in your root App component
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```tsx
|
|
131
|
-
* function App() {
|
|
132
|
-
* usePrefetch();
|
|
133
|
-
* return <Routes>...</Routes>;
|
|
134
|
-
* }
|
|
135
|
-
* ```
|
|
136
|
-
*/
|
|
137
|
-
declare function usePrefetch(): PrefetchManager | null;
|
|
138
|
-
/**
|
|
139
|
-
* Get the prefetch manager instance
|
|
140
|
-
* Useful for manual prefetch control
|
|
141
|
-
*/
|
|
142
|
-
declare function getPrefetchManager(): PrefetchManager | null;
|
|
143
|
-
|
|
144
|
-
/**
|
|
145
|
-
* TanStack Router Hook for Smart Prefetch
|
|
146
|
-
* Automatically prefetches routes based on navigation
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* ```tsx
|
|
150
|
-
* import { usePrefetchTanStack } from 'vite-plugin-smart-prefetch/react';
|
|
151
|
-
*
|
|
152
|
-
* export function RootLayout() {
|
|
153
|
-
* usePrefetchTanStack();
|
|
154
|
-
* return <Outlet />;
|
|
155
|
-
* }
|
|
156
|
-
* ```
|
|
157
|
-
*/
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* React hook to enable smart prefetching with TanStack Router
|
|
161
|
-
* Call this once in your root layout component
|
|
162
|
-
*
|
|
163
|
-
* Supports dynamic routes with patterns:
|
|
164
|
-
* - Static routes: /dashboard, /orders
|
|
165
|
-
* - Dynamic routes: /orders/:id, /users/$userId
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* ```tsx
|
|
169
|
-
* function RootLayout() {
|
|
170
|
-
* usePrefetchTanStack();
|
|
171
|
-
* return <Outlet />;
|
|
172
|
-
* }
|
|
173
|
-
* ```
|
|
174
|
-
*/
|
|
175
|
-
declare function usePrefetchTanStack(): PrefetchManager | null;
|
|
176
|
-
/**
|
|
177
|
-
* Get the prefetch manager instance
|
|
178
|
-
* Useful for manual prefetch control
|
|
179
|
-
*
|
|
180
|
-
* @example
|
|
181
|
-
* ```tsx
|
|
182
|
-
* const manager = getPrefetchManager();
|
|
183
|
-
* manager?.setSegment('premium');
|
|
184
|
-
* ```
|
|
185
|
-
*/
|
|
186
|
-
declare function getPrefetchManagerTanStack(): PrefetchManager | null;
|
|
187
|
-
/**
|
|
188
|
-
* Advanced: Use route pattern matching directly
|
|
189
|
-
* Useful if you need to manually check pattern matching logic
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* ```tsx
|
|
193
|
-
* const matchesPattern = matchPrefetchPattern('/orders/123', '/orders/:id');
|
|
194
|
-
* ```
|
|
195
|
-
*/
|
|
196
|
-
declare function matchPrefetchPattern(pathname: string, pattern: string): boolean;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Enhanced Link Component with Prefetch Support
|
|
200
|
-
* Extends React Router Link with smart prefetching
|
|
201
|
-
*/
|
|
202
|
-
|
|
203
|
-
interface PrefetchLinkProps extends Omit<LinkProps, 'prefetch'> {
|
|
204
|
-
/**
|
|
205
|
-
* Prefetch behavior
|
|
206
|
-
* - 'hover': Prefetch on mouse enter
|
|
207
|
-
* - 'visible': Prefetch when link becomes visible
|
|
208
|
-
* - 'manual': No automatic prefetch (use onClick)
|
|
209
|
-
* - undefined: Use default strategy from config
|
|
210
|
-
*/
|
|
211
|
-
prefetch?: 'hover' | 'visible' | 'manual';
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Enhanced Link component with prefetching
|
|
215
|
-
*
|
|
216
|
-
* @example
|
|
217
|
-
* ```tsx
|
|
218
|
-
* // Prefetch on hover
|
|
219
|
-
* <PrefetchLink to="/orders" prefetch="hover">
|
|
220
|
-
* View Orders
|
|
221
|
-
* </PrefetchLink>
|
|
222
|
-
*
|
|
223
|
-
* // Prefetch when visible
|
|
224
|
-
* <PrefetchLink to="/dispatch-order" prefetch="visible">
|
|
225
|
-
* Create Dispatch
|
|
226
|
-
* </PrefetchLink>
|
|
227
|
-
* ```
|
|
228
|
-
*/
|
|
229
|
-
declare const PrefetchLink: React.ForwardRefExoticComponent<PrefetchLinkProps & React.RefAttributes<HTMLAnchorElement>>;
|
|
230
|
-
|
|
231
216
|
interface PrefetchDebugPanelProps {
|
|
232
217
|
manager: PrefetchManager | null;
|
|
233
218
|
position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
@@ -235,4 +220,4 @@ interface PrefetchDebugPanelProps {
|
|
|
235
220
|
}
|
|
236
221
|
declare function PrefetchDebugPanel({ manager, position, defaultOpen, }: PrefetchDebugPanelProps): react_jsx_runtime.JSX.Element | null;
|
|
237
222
|
|
|
238
|
-
export {
|
|
223
|
+
export { type PrefetchConfig, PrefetchDebugPanel, type PrefetchDebugPanelProps, PrefetchManager, type PrefetchStrategy, type PrefetchTarget };
|
package/dist/react/index.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
// src/frameworks/react/usePrefetch.ts
|
|
2
|
-
import { useEffect, useRef } from "react";
|
|
3
|
-
import { useLocation } from "react-router-dom";
|
|
4
|
-
|
|
5
1
|
// src/runtime/prefetch-manager.ts
|
|
6
2
|
var PrefetchManager = class {
|
|
7
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Constructor
|
|
5
|
+
* @param strategy Prefetch strategy: 'auto', 'hover', 'visible', 'idle', or 'hybrid'
|
|
6
|
+
* @param debug Enable debug logging
|
|
7
|
+
* @param initialLocation Optional initial location (pathname)
|
|
8
|
+
*/
|
|
9
|
+
constructor(strategy = "hybrid", debug = false, initialLocation) {
|
|
8
10
|
this.config = null;
|
|
9
11
|
this.prefetched = /* @__PURE__ */ new Set();
|
|
10
12
|
this.observer = null;
|
|
11
|
-
this.
|
|
12
|
-
this.fallbackToDefault = true;
|
|
13
|
+
this.currentLocation = null;
|
|
13
14
|
this.strategy = strategy;
|
|
14
15
|
this.debug = debug;
|
|
16
|
+
this.currentLocation = initialLocation || null;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Initialize the prefetch manager
|
|
@@ -73,25 +75,6 @@ var PrefetchManager = class {
|
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Set the user segment for segment-based prefetch rules
|
|
78
|
-
* @param segment - The user's segment (e.g., 'premium', 'free', 'admin')
|
|
79
|
-
* @param fallbackToDefault - Use default rules if segment rules unavailable
|
|
80
|
-
*/
|
|
81
|
-
setSegment(segment, fallbackToDefault = true) {
|
|
82
|
-
this.currentSegment = segment;
|
|
83
|
-
this.fallbackToDefault = fallbackToDefault;
|
|
84
|
-
if (this.debug) {
|
|
85
|
-
console.log(`\u{1F504} Segment updated: ${segment || "(none)"}`);
|
|
86
|
-
console.log(` Fallback to default: ${fallbackToDefault}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Get the current segment
|
|
91
|
-
*/
|
|
92
|
-
getSegment() {
|
|
93
|
-
return this.currentSegment;
|
|
94
|
-
}
|
|
95
78
|
/**
|
|
96
79
|
* Match pathname against a route pattern
|
|
97
80
|
* Supports both React Router (:id) and TanStack Router ($id) syntax
|
|
@@ -107,6 +90,30 @@ var PrefetchManager = class {
|
|
|
107
90
|
);
|
|
108
91
|
return patternRegex.test(pathname);
|
|
109
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Update current location and trigger prefetch
|
|
95
|
+
* Call this whenever the application's location changes
|
|
96
|
+
*
|
|
97
|
+
* @param pathname The current pathname (can be from location.pathname, useLocation().pathname, etc.)
|
|
98
|
+
* @example
|
|
99
|
+
* ```tsx
|
|
100
|
+
* // In React Router DOM
|
|
101
|
+
* const location = useLocation();
|
|
102
|
+
* useEffect(() => {
|
|
103
|
+
* manager.onLocationChange(location.pathname);
|
|
104
|
+
* }, [location.pathname]);
|
|
105
|
+
*
|
|
106
|
+
* // In TanStack Router
|
|
107
|
+
* const location = useLocation();
|
|
108
|
+
* useEffect(() => {
|
|
109
|
+
* manager.onLocationChange(location.pathname);
|
|
110
|
+
* }, [location.pathname]);
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
onLocationChange(pathname) {
|
|
114
|
+
this.currentLocation = pathname;
|
|
115
|
+
this.prefetch(pathname);
|
|
116
|
+
}
|
|
110
117
|
/**
|
|
111
118
|
* Prefetch routes based on current route
|
|
112
119
|
*/
|
|
@@ -162,23 +169,12 @@ var PrefetchManager = class {
|
|
|
162
169
|
}
|
|
163
170
|
return;
|
|
164
171
|
}
|
|
165
|
-
|
|
166
|
-
let ruleSource = "default";
|
|
167
|
-
if (this.currentSegment && routeConfig.segments?.[this.currentSegment]) {
|
|
168
|
-
prefetchTargets = routeConfig.segments[this.currentSegment];
|
|
169
|
-
ruleSource = `segment (${this.currentSegment})`;
|
|
170
|
-
} else if (this.currentSegment && !routeConfig.segments?.[this.currentSegment] && !this.fallbackToDefault) {
|
|
171
|
-
if (this.debug) {
|
|
172
|
-
console.warn(`\u26A0\uFE0F No prefetch rules for segment "${this.currentSegment}" and fallback disabled`);
|
|
173
|
-
}
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
172
|
+
const prefetchTargets = routeConfig.prefetch;
|
|
176
173
|
console.log(`\u2705 Found prefetch rule for: ${matchedRoute}`);
|
|
177
174
|
console.log(` Total targets to prefetch: ${prefetchTargets.length}`);
|
|
178
|
-
console.log(` Using: ${ruleSource} rules`);
|
|
179
175
|
console.log(` Strategy: ${this.strategy}`);
|
|
180
176
|
if (this.debug) {
|
|
181
|
-
console.groupCollapsed(`\u{1F4CA} Prefetch Rules for: ${matchedRoute}
|
|
177
|
+
console.groupCollapsed(`\u{1F4CA} Prefetch Rules for: ${matchedRoute}`);
|
|
182
178
|
prefetchTargets.forEach((target, index) => {
|
|
183
179
|
console.log(` ${index + 1}. ${target.route} (${target.priority} priority, ${(target.probability * 100).toFixed(1)}%)`);
|
|
184
180
|
});
|
|
@@ -543,126 +539,9 @@ var PrefetchManager = class {
|
|
|
543
539
|
}
|
|
544
540
|
};
|
|
545
541
|
|
|
546
|
-
// src/frameworks/react/usePrefetch.ts
|
|
547
|
-
var managerInstance = null;
|
|
548
|
-
function usePrefetch() {
|
|
549
|
-
const location = useLocation();
|
|
550
|
-
const initialized = useRef(false);
|
|
551
|
-
useEffect(() => {
|
|
552
|
-
if (!initialized.current) {
|
|
553
|
-
const config = window.__SMART_PREFETCH__ || {};
|
|
554
|
-
const strategy = config.strategy || "hybrid";
|
|
555
|
-
const debug = config.debug || false;
|
|
556
|
-
managerInstance = new PrefetchManager(strategy, debug);
|
|
557
|
-
managerInstance.init();
|
|
558
|
-
window.__FARMART_PREFETCH_MANAGER__ = managerInstance;
|
|
559
|
-
initialized.current = true;
|
|
560
|
-
if (debug) {
|
|
561
|
-
console.log("\u2705 usePrefetch initialized");
|
|
562
|
-
console.log("\u2705 Prefetch manager exposed as window.__FARMART_PREFETCH_MANAGER__");
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
}, []);
|
|
566
|
-
useEffect(() => {
|
|
567
|
-
if (managerInstance) {
|
|
568
|
-
managerInstance.prefetch(location.pathname);
|
|
569
|
-
}
|
|
570
|
-
}, [location.pathname]);
|
|
571
|
-
return managerInstance;
|
|
572
|
-
}
|
|
573
|
-
function getPrefetchManager() {
|
|
574
|
-
return managerInstance;
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
// src/frameworks/react/usePrefetchTanStack.ts
|
|
578
|
-
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
579
|
-
import { useLocation as useLocation2 } from "@tanstack/react-router";
|
|
580
|
-
var managerInstance2 = null;
|
|
581
|
-
function usePrefetchTanStack() {
|
|
582
|
-
const location = useLocation2();
|
|
583
|
-
const initialized = useRef2(false);
|
|
584
|
-
useEffect2(() => {
|
|
585
|
-
if (!initialized.current) {
|
|
586
|
-
const config = window.__SMART_PREFETCH__ || {};
|
|
587
|
-
const strategy = config.strategy || "hybrid";
|
|
588
|
-
const debug = config.debug || false;
|
|
589
|
-
managerInstance2 = new PrefetchManager(strategy, debug);
|
|
590
|
-
managerInstance2.init();
|
|
591
|
-
window.__FARMART_PREFETCH_MANAGER__ = managerInstance2;
|
|
592
|
-
initialized.current = true;
|
|
593
|
-
if (debug) {
|
|
594
|
-
console.log("\u2705 usePrefetchTanStack initialized");
|
|
595
|
-
console.log("\u2705 Prefetch manager exposed as window.__FARMART_PREFETCH_MANAGER__");
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
}, []);
|
|
599
|
-
useEffect2(() => {
|
|
600
|
-
if (managerInstance2) {
|
|
601
|
-
const pathname = location.pathname.split("?")[0].split("#")[0];
|
|
602
|
-
managerInstance2.prefetch(pathname);
|
|
603
|
-
}
|
|
604
|
-
}, [location.pathname]);
|
|
605
|
-
return managerInstance2;
|
|
606
|
-
}
|
|
607
|
-
function getPrefetchManagerTanStack() {
|
|
608
|
-
return managerInstance2;
|
|
609
|
-
}
|
|
610
|
-
function matchPrefetchPattern(pathname, pattern) {
|
|
611
|
-
const patternRegex = new RegExp(
|
|
612
|
-
"^" + pattern.replace(/:[^/]+/g, "[^/]+").replace(/\$[^/]+/g, "[^/]+").replace(/\*/g, ".*") + // Match wildcard
|
|
613
|
-
"$"
|
|
614
|
-
);
|
|
615
|
-
return patternRegex.test(pathname);
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
// src/frameworks/react/PrefetchLink.tsx
|
|
619
|
-
import React, { useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
620
|
-
import { Link } from "react-router-dom";
|
|
621
|
-
import { jsx } from "react/jsx-runtime";
|
|
622
|
-
var PrefetchLink = React.forwardRef(
|
|
623
|
-
({ prefetch, to, children, onMouseEnter, ...props }, forwardedRef) => {
|
|
624
|
-
const linkRef = useRef3(null);
|
|
625
|
-
const manager = getPrefetchManager();
|
|
626
|
-
const route = typeof to === "string" ? to : to.pathname || "";
|
|
627
|
-
useEffect3(() => {
|
|
628
|
-
if (prefetch === "visible" && linkRef.current && manager) {
|
|
629
|
-
manager.observeLink(linkRef.current, route);
|
|
630
|
-
}
|
|
631
|
-
}, [prefetch, route, manager]);
|
|
632
|
-
const handleMouseEnter = (e) => {
|
|
633
|
-
if (prefetch === "hover" && manager) {
|
|
634
|
-
manager.prefetchRoute(route);
|
|
635
|
-
}
|
|
636
|
-
if (onMouseEnter) {
|
|
637
|
-
onMouseEnter(e);
|
|
638
|
-
}
|
|
639
|
-
};
|
|
640
|
-
return /* @__PURE__ */ jsx(
|
|
641
|
-
Link,
|
|
642
|
-
{
|
|
643
|
-
ref: (node) => {
|
|
644
|
-
if (node) {
|
|
645
|
-
linkRef.current = node;
|
|
646
|
-
if (typeof forwardedRef === "function") {
|
|
647
|
-
forwardedRef(node);
|
|
648
|
-
} else if (forwardedRef) {
|
|
649
|
-
forwardedRef.current = node;
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
},
|
|
653
|
-
to,
|
|
654
|
-
onMouseEnter: handleMouseEnter,
|
|
655
|
-
...props,
|
|
656
|
-
children
|
|
657
|
-
}
|
|
658
|
-
);
|
|
659
|
-
}
|
|
660
|
-
);
|
|
661
|
-
PrefetchLink.displayName = "PrefetchLink";
|
|
662
|
-
|
|
663
542
|
// src/frameworks/react/PrefetchDebugPanel.tsx
|
|
664
|
-
import { useEffect
|
|
665
|
-
import { jsx
|
|
543
|
+
import { useEffect, useState } from "react";
|
|
544
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
666
545
|
function PrefetchDebugPanel({
|
|
667
546
|
manager,
|
|
668
547
|
position = "bottom-right",
|
|
@@ -671,7 +550,7 @@ function PrefetchDebugPanel({
|
|
|
671
550
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
672
551
|
const [stats, setStats] = useState(null);
|
|
673
552
|
const [links, setLinks] = useState([]);
|
|
674
|
-
|
|
553
|
+
useEffect(() => {
|
|
675
554
|
if (!manager) return;
|
|
676
555
|
const updateStats = () => {
|
|
677
556
|
setStats(manager.getStats());
|
|
@@ -753,33 +632,33 @@ function PrefetchDebugPanel({
|
|
|
753
632
|
};
|
|
754
633
|
return /* @__PURE__ */ jsxs("div", { style: containerStyle, children: [
|
|
755
634
|
isOpen && stats && /* @__PURE__ */ jsxs("div", { style: panelStyle, children: [
|
|
756
|
-
/* @__PURE__ */
|
|
635
|
+
/* @__PURE__ */ jsx("div", { style: headerStyle, children: "\u{1F680} Smart Prefetch Debug" }),
|
|
757
636
|
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "12px" }, children: [
|
|
758
637
|
/* @__PURE__ */ jsxs("div", { style: statStyle, children: [
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
/* @__PURE__ */
|
|
638
|
+
/* @__PURE__ */ jsx("span", { children: "Strategy:" }),
|
|
639
|
+
/* @__PURE__ */ jsx("strong", { children: stats.strategy })
|
|
761
640
|
] }),
|
|
762
641
|
/* @__PURE__ */ jsxs("div", { style: statStyle, children: [
|
|
763
|
-
/* @__PURE__ */
|
|
764
|
-
/* @__PURE__ */
|
|
642
|
+
/* @__PURE__ */ jsx("span", { children: "Config Loaded:" }),
|
|
643
|
+
/* @__PURE__ */ jsx("strong", { children: stats.configLoaded ? "\u2705" : "\u274C" })
|
|
765
644
|
] }),
|
|
766
645
|
/* @__PURE__ */ jsxs("div", { style: statStyle, children: [
|
|
767
|
-
/* @__PURE__ */
|
|
768
|
-
/* @__PURE__ */
|
|
646
|
+
/* @__PURE__ */ jsx("span", { children: "Total Prefetched:" }),
|
|
647
|
+
/* @__PURE__ */ jsx("strong", { children: stats.totalPrefetched })
|
|
769
648
|
] }),
|
|
770
649
|
/* @__PURE__ */ jsxs("div", { style: statStyle, children: [
|
|
771
|
-
/* @__PURE__ */
|
|
772
|
-
/* @__PURE__ */
|
|
650
|
+
/* @__PURE__ */ jsx("span", { children: "Link Tags in DOM:" }),
|
|
651
|
+
/* @__PURE__ */ jsx("strong", { children: links.length })
|
|
773
652
|
] })
|
|
774
653
|
] }),
|
|
775
654
|
stats.prefetchedRoutes.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
776
|
-
/* @__PURE__ */
|
|
777
|
-
/* @__PURE__ */
|
|
655
|
+
/* @__PURE__ */ jsx("div", { style: { ...headerStyle, fontSize: "11px" }, children: "Prefetched Routes:" }),
|
|
656
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: "11px", color: "#666", marginBottom: "8px" }, children: stats.prefetchedRoutes.join(", ") })
|
|
778
657
|
] }),
|
|
779
658
|
links.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
780
|
-
/* @__PURE__ */
|
|
659
|
+
/* @__PURE__ */ jsx("div", { style: { ...headerStyle, fontSize: "11px" }, children: "Active Link Tags:" }),
|
|
781
660
|
links.map((link, i) => /* @__PURE__ */ jsxs("div", { style: linkStyle, children: [
|
|
782
|
-
/* @__PURE__ */
|
|
661
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("strong", { children: link.route }) }),
|
|
783
662
|
/* @__PURE__ */ jsxs("div", { style: { color: "#666", marginTop: "4px" }, children: [
|
|
784
663
|
"Priority: ",
|
|
785
664
|
link.priority,
|
|
@@ -787,10 +666,10 @@ function PrefetchDebugPanel({
|
|
|
787
666
|
(parseFloat(link.probability) * 100).toFixed(1),
|
|
788
667
|
"%"
|
|
789
668
|
] }),
|
|
790
|
-
/* @__PURE__ */
|
|
669
|
+
/* @__PURE__ */ jsx("div", { style: { color: "#999", marginTop: "2px", wordBreak: "break-all" }, children: link.href.split("/").pop() })
|
|
791
670
|
] }, i))
|
|
792
671
|
] }),
|
|
793
|
-
/* @__PURE__ */
|
|
672
|
+
/* @__PURE__ */ jsx(
|
|
794
673
|
"button",
|
|
795
674
|
{
|
|
796
675
|
onClick: () => {
|
|
@@ -810,7 +689,7 @@ function PrefetchDebugPanel({
|
|
|
810
689
|
}
|
|
811
690
|
)
|
|
812
691
|
] }),
|
|
813
|
-
/* @__PURE__ */
|
|
692
|
+
/* @__PURE__ */ jsx(
|
|
814
693
|
"button",
|
|
815
694
|
{
|
|
816
695
|
style: buttonStyle,
|
|
@@ -823,11 +702,6 @@ function PrefetchDebugPanel({
|
|
|
823
702
|
}
|
|
824
703
|
export {
|
|
825
704
|
PrefetchDebugPanel,
|
|
826
|
-
|
|
827
|
-
getPrefetchManager,
|
|
828
|
-
getPrefetchManagerTanStack,
|
|
829
|
-
matchPrefetchPattern,
|
|
830
|
-
usePrefetch,
|
|
831
|
-
usePrefetchTanStack
|
|
705
|
+
PrefetchManager
|
|
832
706
|
};
|
|
833
707
|
//# sourceMappingURL=index.js.map
|