@flight-framework/router 0.0.3 → 0.0.4
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/README.md +251 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,14 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
Universal client-side routing primitives for Flight Framework. Zero external dependencies. Works with any UI framework.
|
|
4
4
|
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Features](#features)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Quick Start](#quick-start)
|
|
10
|
+
- [Prefetch Strategies](#prefetch-strategies)
|
|
11
|
+
- [Smart Prefetching](#smart-prefetching)
|
|
12
|
+
- [Intercepting Routes](#intercepting-routes)
|
|
13
|
+
- [Programmatic Prefetching](#programmatic-prefetching)
|
|
14
|
+
- [Prefetch Queue](#prefetch-queue)
|
|
15
|
+
- [React Hooks](#react-hooks)
|
|
16
|
+
- [Programmatic Navigation](#programmatic-navigation)
|
|
17
|
+
- [Route Matching](#route-matching)
|
|
18
|
+
- [Link Component](#link-component)
|
|
19
|
+
- [Framework Integration](#framework-integration)
|
|
20
|
+
- [SSR Support](#ssr-support)
|
|
21
|
+
- [Browser Support](#browser-support)
|
|
22
|
+
- [License](#license)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
5
26
|
## Features
|
|
6
27
|
|
|
7
|
-
- Multiple prefetch strategies (none, intent, render, viewport)
|
|
28
|
+
- Multiple prefetch strategies (none, intent, render, viewport, idle)
|
|
29
|
+
- Network-aware smart prefetching (respects Save-Data and connection speed)
|
|
30
|
+
- Intercepting routes with modal support
|
|
31
|
+
- Prefetch queue with concurrency control
|
|
8
32
|
- SSR-safe implementation
|
|
9
33
|
- Framework-agnostic with React adapters
|
|
10
34
|
- TypeScript-first design
|
|
11
35
|
- IntersectionObserver for viewport prefetching
|
|
12
|
-
-
|
|
36
|
+
- Zero external dependencies
|
|
37
|
+
|
|
38
|
+
---
|
|
13
39
|
|
|
14
40
|
## Installation
|
|
15
41
|
|
|
@@ -17,6 +43,8 @@ Universal client-side routing primitives for Flight Framework. Zero external dep
|
|
|
17
43
|
npm install @flight-framework/router
|
|
18
44
|
```
|
|
19
45
|
|
|
46
|
+
---
|
|
47
|
+
|
|
20
48
|
## Quick Start
|
|
21
49
|
|
|
22
50
|
### With React
|
|
@@ -57,6 +85,8 @@ function Content() {
|
|
|
57
85
|
}
|
|
58
86
|
```
|
|
59
87
|
|
|
88
|
+
---
|
|
89
|
+
|
|
60
90
|
## Prefetch Strategies
|
|
61
91
|
|
|
62
92
|
Flight Router supports multiple prefetch strategies to optimize navigation performance:
|
|
@@ -67,6 +97,7 @@ Flight Router supports multiple prefetch strategies to optimize navigation perfo
|
|
|
67
97
|
| `'intent'` | Prefetch on hover/focus | Most navigation links |
|
|
68
98
|
| `'render'` | Prefetch immediately | Critical paths (checkout) |
|
|
69
99
|
| `'viewport'` | Prefetch when visible | Mobile, infinite scroll |
|
|
100
|
+
| `'idle'` | Prefetch when browser is idle | Background preloading |
|
|
70
101
|
|
|
71
102
|
### Usage Examples
|
|
72
103
|
|
|
@@ -84,8 +115,129 @@ Flight Router supports multiple prefetch strategies to optimize navigation perfo
|
|
|
84
115
|
|
|
85
116
|
// Prefetch when link enters viewport (good for mobile)
|
|
86
117
|
<Link href="/products" prefetch="viewport">Products</Link>
|
|
118
|
+
|
|
119
|
+
// Prefetch when browser is idle
|
|
120
|
+
<Link href="/settings" prefetch="idle">Settings</Link>
|
|
87
121
|
```
|
|
88
122
|
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Smart Prefetching
|
|
126
|
+
|
|
127
|
+
Network-aware prefetching that respects user preferences and connection quality.
|
|
128
|
+
|
|
129
|
+
### Features
|
|
130
|
+
|
|
131
|
+
- Respects `Save-Data` header (users on limited data plans)
|
|
132
|
+
- Detects connection type (2G, 3G, 4G)
|
|
133
|
+
- Configurable minimum network requirements
|
|
134
|
+
- Automatic throttling on slow connections
|
|
135
|
+
|
|
136
|
+
### API
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import {
|
|
140
|
+
smartPrefetch,
|
|
141
|
+
shouldSkipPrefetch,
|
|
142
|
+
canPrefetchOnNetwork,
|
|
143
|
+
} from '@flight-framework/router';
|
|
144
|
+
|
|
145
|
+
// Respects network conditions automatically
|
|
146
|
+
smartPrefetch('/dashboard');
|
|
147
|
+
|
|
148
|
+
// Check if prefetching should be skipped
|
|
149
|
+
if (shouldSkipPrefetch()) {
|
|
150
|
+
console.log('Skipping due to network conditions');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Custom network requirements
|
|
154
|
+
const canPrefetch = canPrefetchOnNetwork({
|
|
155
|
+
respectSaveData: true, // Skip if Save-Data enabled
|
|
156
|
+
respectSlowNetwork: true, // Skip on 2G/slow-2G
|
|
157
|
+
minEffectiveType: '3g', // Minimum 3G required
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Configuration
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
smartPrefetch('/page', {
|
|
165
|
+
respectSaveData: true, // Default: true
|
|
166
|
+
respectSlowNetwork: true, // Default: true
|
|
167
|
+
minEffectiveType: '3g', // Default: '3g'
|
|
168
|
+
priority: 'high', // Optional priority override
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Intercepting Routes
|
|
175
|
+
|
|
176
|
+
Render routes in modals while preserving URL state. Perfect for photo galleries, user profiles, and detail views.
|
|
177
|
+
|
|
178
|
+
### React Integration
|
|
179
|
+
|
|
180
|
+
```tsx
|
|
181
|
+
import {
|
|
182
|
+
InterceptedRouteProvider,
|
|
183
|
+
useInterceptedRoute,
|
|
184
|
+
} from '@flight-framework/router';
|
|
185
|
+
|
|
186
|
+
// Wrap your layout
|
|
187
|
+
function RootLayout({ children }) {
|
|
188
|
+
return (
|
|
189
|
+
<InterceptedRouteProvider>
|
|
190
|
+
{children}
|
|
191
|
+
<ModalRenderer />
|
|
192
|
+
</InterceptedRouteProvider>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Render intercepted content in a modal
|
|
197
|
+
function ModalRenderer() {
|
|
198
|
+
const intercepted = useInterceptedRoute();
|
|
199
|
+
|
|
200
|
+
if (!intercepted) return null;
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<Dialog open onClose={intercepted.dismiss}>
|
|
204
|
+
<intercepted.Component />
|
|
205
|
+
<button onClick={intercepted.navigateToPage}>
|
|
206
|
+
View Full Page
|
|
207
|
+
</button>
|
|
208
|
+
</Dialog>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Intercepted Route State
|
|
214
|
+
|
|
215
|
+
| Property | Type | Description |
|
|
216
|
+
|----------|------|-------------|
|
|
217
|
+
| `Component` | `() => unknown` | The component to render |
|
|
218
|
+
| `pathname` | `string` | The intercepted URL path |
|
|
219
|
+
| `params` | `Record<string, string>` | Route parameters |
|
|
220
|
+
| `dismiss()` | `() => void` | Go back (close modal) |
|
|
221
|
+
| `navigateToPage()` | `() => void` | Navigate to actual page |
|
|
222
|
+
|
|
223
|
+
### Additional Hooks
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import {
|
|
227
|
+
useInterceptedRoute,
|
|
228
|
+
useSetInterceptedRoute,
|
|
229
|
+
useIsIntercepting,
|
|
230
|
+
} from '@flight-framework/router';
|
|
231
|
+
|
|
232
|
+
// Check if currently intercepting
|
|
233
|
+
const isIntercepting = useIsIntercepting();
|
|
234
|
+
|
|
235
|
+
// Programmatically set intercepted state (for router integration)
|
|
236
|
+
const setIntercepted = useSetInterceptedRoute();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
89
241
|
## Programmatic Prefetching
|
|
90
242
|
|
|
91
243
|
```typescript
|
|
@@ -94,6 +246,7 @@ import {
|
|
|
94
246
|
prefetchAll,
|
|
95
247
|
prefetchWhenIdle,
|
|
96
248
|
isPrefetched,
|
|
249
|
+
clearPrefetchCache,
|
|
97
250
|
} from '@flight-framework/router';
|
|
98
251
|
|
|
99
252
|
// Basic prefetch
|
|
@@ -115,33 +268,50 @@ prefetchWhenIdle('/dashboard');
|
|
|
115
268
|
if (!isPrefetched('/docs')) {
|
|
116
269
|
prefetch('/docs');
|
|
117
270
|
}
|
|
271
|
+
|
|
272
|
+
// Clear prefetch cache (useful for testing)
|
|
273
|
+
clearPrefetchCache();
|
|
118
274
|
```
|
|
119
275
|
|
|
120
|
-
|
|
276
|
+
---
|
|
121
277
|
|
|
122
|
-
|
|
278
|
+
## Prefetch Queue
|
|
123
279
|
|
|
124
|
-
|
|
125
|
-
import { PrefetchPageLinks } from '@flight-framework/router';
|
|
280
|
+
Control concurrent prefetch requests to avoid overwhelming the network:
|
|
126
281
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
282
|
+
```typescript
|
|
283
|
+
import { PrefetchQueue } from '@flight-framework/router';
|
|
284
|
+
|
|
285
|
+
// Create queue with max 3 concurrent prefetches
|
|
286
|
+
const queue = new PrefetchQueue(3);
|
|
287
|
+
|
|
288
|
+
// Add URLs to queue
|
|
289
|
+
queue.add('/page1');
|
|
290
|
+
queue.add('/page2', { priority: 'high' });
|
|
291
|
+
queue.addAll(['/page3', '/page4', '/page5']);
|
|
292
|
+
|
|
293
|
+
// Control queue
|
|
294
|
+
queue.pause(); // Stop processing
|
|
295
|
+
queue.resume(); // Continue processing
|
|
296
|
+
queue.clear(); // Remove pending items
|
|
297
|
+
|
|
298
|
+
// Check state
|
|
299
|
+
console.log(queue.pending); // Items waiting
|
|
300
|
+
console.log(queue.activeCount); // Currently prefetching
|
|
140
301
|
```
|
|
141
302
|
|
|
142
|
-
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## React Hooks
|
|
143
306
|
|
|
144
307
|
```tsx
|
|
308
|
+
import {
|
|
309
|
+
useRouter,
|
|
310
|
+
useParams,
|
|
311
|
+
useSearchParams,
|
|
312
|
+
usePathname,
|
|
313
|
+
} from '@flight-framework/router';
|
|
314
|
+
|
|
145
315
|
// Get current path and navigation functions
|
|
146
316
|
const { path, searchParams, navigate, back, forward } = useRouter();
|
|
147
317
|
|
|
@@ -155,6 +325,8 @@ const [searchParams, setSearchParams] = useSearchParams();
|
|
|
155
325
|
const pathname = usePathname();
|
|
156
326
|
```
|
|
157
327
|
|
|
328
|
+
---
|
|
329
|
+
|
|
158
330
|
## Programmatic Navigation
|
|
159
331
|
|
|
160
332
|
```typescript
|
|
@@ -173,6 +345,8 @@ navigate('/next-page', { scroll: false });
|
|
|
173
345
|
navigate('/dashboard', { state: { from: '/login' } });
|
|
174
346
|
```
|
|
175
347
|
|
|
348
|
+
---
|
|
349
|
+
|
|
176
350
|
## Route Matching
|
|
177
351
|
|
|
178
352
|
```typescript
|
|
@@ -191,7 +365,11 @@ const path = generatePath('/docs/:slug', { slug: 'api-routes' });
|
|
|
191
365
|
// '/docs/api-routes'
|
|
192
366
|
```
|
|
193
367
|
|
|
194
|
-
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Link Component
|
|
371
|
+
|
|
372
|
+
### Props
|
|
195
373
|
|
|
196
374
|
| Prop | Type | Default | Description |
|
|
197
375
|
|------|------|---------|-------------|
|
|
@@ -203,7 +381,32 @@ const path = generatePath('/docs/:slug', { slug: 'api-routes' });
|
|
|
203
381
|
| `className` | `string` | - | CSS class |
|
|
204
382
|
| `aria-label` | `string` | - | Accessibility label |
|
|
205
383
|
|
|
206
|
-
|
|
384
|
+
### PrefetchPageLinks Component
|
|
385
|
+
|
|
386
|
+
For proactive prefetching based on user behavior:
|
|
387
|
+
|
|
388
|
+
```tsx
|
|
389
|
+
import { PrefetchPageLinks } from '@flight-framework/router';
|
|
390
|
+
|
|
391
|
+
function SearchResults({ results }) {
|
|
392
|
+
return (
|
|
393
|
+
<>
|
|
394
|
+
{results.map(result => (
|
|
395
|
+
<div key={result.id}>
|
|
396
|
+
<PrefetchPageLinks page={result.url} />
|
|
397
|
+
<Link href={result.url}>{result.title}</Link>
|
|
398
|
+
</div>
|
|
399
|
+
))}
|
|
400
|
+
</>
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Framework Integration
|
|
408
|
+
|
|
409
|
+
### Vue
|
|
207
410
|
|
|
208
411
|
```vue
|
|
209
412
|
<script setup>
|
|
@@ -217,7 +420,7 @@ const docsLink = useLinkProps('/docs', { prefetch: 'intent' });
|
|
|
217
420
|
</template>
|
|
218
421
|
```
|
|
219
422
|
|
|
220
|
-
|
|
423
|
+
### Vanilla JavaScript
|
|
221
424
|
|
|
222
425
|
```typescript
|
|
223
426
|
import { createLink, prefetch } from '@flight-framework/router';
|
|
@@ -231,6 +434,8 @@ const link = createLink({
|
|
|
231
434
|
document.body.appendChild(link);
|
|
232
435
|
```
|
|
233
436
|
|
|
437
|
+
---
|
|
438
|
+
|
|
234
439
|
## SSR Support
|
|
235
440
|
|
|
236
441
|
The router is SSR-safe. Pass the initial path from your server:
|
|
@@ -246,19 +451,7 @@ export function render(url: string) {
|
|
|
246
451
|
}
|
|
247
452
|
```
|
|
248
453
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
For optimal prefetching, Flight generates a route manifest during build that maps routes to their JS modules. This enables `prefetch` to preload the correct chunks.
|
|
252
|
-
|
|
253
|
-
```typescript
|
|
254
|
-
// flight.config.ts
|
|
255
|
-
export default defineConfig({
|
|
256
|
-
router: {
|
|
257
|
-
// Generates __FLIGHT_MANIFEST__ at build time
|
|
258
|
-
generateManifest: true,
|
|
259
|
-
},
|
|
260
|
-
});
|
|
261
|
-
```
|
|
454
|
+
---
|
|
262
455
|
|
|
263
456
|
## Browser Support
|
|
264
457
|
|
|
@@ -266,8 +459,30 @@ export default defineConfig({
|
|
|
266
459
|
|---------|--------|---------|--------|------|
|
|
267
460
|
| Prefetch | All | All | All | All |
|
|
268
461
|
| Viewport (IntersectionObserver) | 51+ | 55+ | 12.1+ | 15+ |
|
|
462
|
+
| Network Information API | 61+ | No | No | 79+ |
|
|
463
|
+
| requestIdleCallback | 47+ | 55+ | No | 79+ |
|
|
269
464
|
| fetchPriority | 101+ | No | No | 101+ |
|
|
270
465
|
|
|
466
|
+
Features gracefully degrade when APIs are unavailable.
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## TypeScript
|
|
471
|
+
|
|
472
|
+
Full TypeScript support with exported types:
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
import type {
|
|
476
|
+
PrefetchStrategy,
|
|
477
|
+
PrefetchOptions,
|
|
478
|
+
SmartPrefetchOptions,
|
|
479
|
+
InterceptedRouteState,
|
|
480
|
+
InterceptedRouteContextValue,
|
|
481
|
+
} from '@flight-framework/router';
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
271
486
|
## License
|
|
272
487
|
|
|
273
488
|
MIT
|