@lukso/transaction-view-headless 0.2.2-dev.a8c9315
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/.turbo/turbo-build.log +51 -0
- package/CHANGELOG.md +88 -0
- package/COMPONENT_ARCHITECTURE.md +190 -0
- package/COMPONENT_CONVERSION_ANALYSIS.md +371 -0
- package/CONTEXT_VARIANT_GUIDE.md +425 -0
- package/LAZY_LOADING_GUIDE.md +534 -0
- package/LICENSE +201 -0
- package/PLAYBACK_EXAMPLES.md +658 -0
- package/PLAYBACK_GUIDE.md +402 -0
- package/README.md +43 -0
- package/REGISTRY_SUMMARY.md +638 -0
- package/SUFFERING_ECONOMICS.md +346 -0
- package/SUFFERING_ECONOMICS.zip +0 -0
- package/VIEW_REGISTRATION_GUIDE.md +795 -0
- package/dist/composables/index.cjs +1321 -0
- package/dist/composables/index.cjs.map +1 -0
- package/dist/composables/index.d.cts +6 -0
- package/dist/composables/index.d.ts +6 -0
- package/dist/composables/index.js +1276 -0
- package/dist/composables/index.js.map +1 -0
- package/dist/index-CMLU1hKL.d.ts +374 -0
- package/dist/index-CSDjhiKV.d.cts +374 -0
- package/dist/index.cjs +1534 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +1463 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/index.cjs +522 -0
- package/dist/registry/index.cjs.map +1 -0
- package/dist/registry/index.d.cts +46 -0
- package/dist/registry/index.d.ts +46 -0
- package/dist/registry/index.js +487 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +203 -0
- package/dist/types/index.d.ts +203 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +217 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +47 -0
- package/dist/utils/index.d.ts +47 -0
- package/dist/utils/index.js +188 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/view-loader-dD86QAlQ.d.cts +121 -0
- package/dist/view-loader-ii8AxiQR.d.ts +121 -0
- package/package.json +64 -0
- package/publish.log +0 -0
- package/src/composables/index.ts +59 -0
- package/src/composables/use-image-loader.ts +315 -0
- package/src/composables/use-transaction-playback.ts +396 -0
- package/src/composables/use-transaction-view.ts +309 -0
- package/src/config/lukso-config.ts +171 -0
- package/src/examples/context-aware-views.ts +300 -0
- package/src/examples/example-views.ts +197 -0
- package/src/examples/lit-plus-rn-strategy.ts +448 -0
- package/src/examples/lsp7-custom-matcher-examples.ts +174 -0
- package/src/examples/opt-in-context-examples.ts +372 -0
- package/src/examples/optimized-view-definitions.ts +408 -0
- package/src/examples/vue-to-lit-compilation.ts +358 -0
- package/src/hooks/useAddressQuery.ts +135 -0
- package/src/hooks/useAddressResolution.ts +437 -0
- package/src/index.ts +36 -0
- package/src/registry/index.ts +13 -0
- package/src/registry/view-loader.ts +305 -0
- package/src/registry/view-registry.ts +135 -0
- package/src/types/index.ts +16 -0
- package/src/types/view-contexts.ts +72 -0
- package/src/types/view-matching.ts +173 -0
- package/src/utils/context-matcher.ts +165 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/view-matcher.ts +338 -0
- package/tsconfig.json +20 -0
- package/tsup.config.ts +34 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
# Lazy Loading Views - Complete Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
View loaders support **lazy loading via callbacks**, preventing components from being bundled until they're actually needed. This reduces initial bundle size and improves app startup performance.
|
|
6
|
+
|
|
7
|
+
## Lazy Loading Syntax
|
|
8
|
+
|
|
9
|
+
### String Path (Static, Bundled)
|
|
10
|
+
```typescript
|
|
11
|
+
loader: { type: 'dynamic-import', path: './Component.vue' }
|
|
12
|
+
```
|
|
13
|
+
Component is bundled with your app.
|
|
14
|
+
|
|
15
|
+
### Callback (Lazy, On-Demand)
|
|
16
|
+
```typescript
|
|
17
|
+
loader: { type: 'dynamic-import', path: () => import('./Component.vue') }
|
|
18
|
+
```
|
|
19
|
+
Component is loaded only when needed.
|
|
20
|
+
|
|
21
|
+
## Helper Functions
|
|
22
|
+
|
|
23
|
+
### Vue Components
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { LoaderHelpers } from '@lukso/transaction-view-headless'
|
|
27
|
+
|
|
28
|
+
// Static (bundled)
|
|
29
|
+
LoaderHelpers.vueComponent('./CustomView.vue')
|
|
30
|
+
|
|
31
|
+
// Lazy (loaded on demand) ✅ RECOMMENDED
|
|
32
|
+
LoaderHelpers.vueComponent(() => import('./CustomView.vue'))
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### React Native Components
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
// Static
|
|
39
|
+
LoaderHelpers.rnComponent('./CustomView.tsx')
|
|
40
|
+
|
|
41
|
+
// Lazy ✅ RECOMMENDED
|
|
42
|
+
LoaderHelpers.rnComponent(() => import('./CustomView.tsx'))
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Lit Components
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// Lit uses custom elements (always lazy by nature)
|
|
49
|
+
LoaderHelpers.litComponent('custom-view')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Complete Examples
|
|
53
|
+
|
|
54
|
+
### 1. Basic Lazy-Loaded Vue View
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
import { LoaderHelpers } from '@lukso/transaction-view-headless'
|
|
58
|
+
import type { ViewDefinition } from '@lukso/transaction-view-headless'
|
|
59
|
+
|
|
60
|
+
const lazyViews: ViewDefinition[] = [
|
|
61
|
+
{
|
|
62
|
+
id: 'lsp7-transfer-vue',
|
|
63
|
+
name: 'LSP7 Transfer (Vue)',
|
|
64
|
+
priority: 120,
|
|
65
|
+
criteria: {
|
|
66
|
+
standard: 'LSP7',
|
|
67
|
+
recordType: 'lsp7-transfer'
|
|
68
|
+
},
|
|
69
|
+
frameworks: {
|
|
70
|
+
lit: {
|
|
71
|
+
loader: LoaderHelpers.litComponent('lsp7-transfer-lit'),
|
|
72
|
+
component: 'lsp7-transfer-lit'
|
|
73
|
+
},
|
|
74
|
+
vue: {
|
|
75
|
+
// Lazy loaded! Only downloads when LSP7 transfer is rendered
|
|
76
|
+
loader: LoaderHelpers.vueComponent(() => import('./views/LSP7Transfer.vue')),
|
|
77
|
+
component: 'LSP7Transfer'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2. Multiple Views with Different Loading Strategies
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
const mixedViews: ViewDefinition[] = [
|
|
88
|
+
// Common view: bundled (used frequently)
|
|
89
|
+
{
|
|
90
|
+
id: 'common-transfer',
|
|
91
|
+
name: 'Common Transfer',
|
|
92
|
+
priority: 100,
|
|
93
|
+
criteria: { recordType: 'transfer' },
|
|
94
|
+
frameworks: {
|
|
95
|
+
vue: {
|
|
96
|
+
loader: LoaderHelpers.vueComponent('./views/CommonTransfer.vue'),
|
|
97
|
+
component: 'CommonTransfer'
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// Rare view: lazy loaded (used infrequently)
|
|
103
|
+
{
|
|
104
|
+
id: 'rare-contract-deployment',
|
|
105
|
+
name: 'Contract Deployment',
|
|
106
|
+
priority: 110,
|
|
107
|
+
criteria: { recordType: 'create' },
|
|
108
|
+
frameworks: {
|
|
109
|
+
vue: {
|
|
110
|
+
loader: LoaderHelpers.vueComponent(() => import('./views/ContractDeploy.vue')),
|
|
111
|
+
component: 'ContractDeploy'
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// Heavy view: lazy loaded (large bundle)
|
|
117
|
+
{
|
|
118
|
+
id: 'heavy-analytics-view',
|
|
119
|
+
name: 'Analytics View',
|
|
120
|
+
priority: 90,
|
|
121
|
+
criteria: { recordType: 'analytics' },
|
|
122
|
+
frameworks: {
|
|
123
|
+
vue: {
|
|
124
|
+
loader: LoaderHelpers.vueComponent(() => import(
|
|
125
|
+
/* webpackChunkName: "analytics" */
|
|
126
|
+
'./views/AnalyticsView.vue'
|
|
127
|
+
)),
|
|
128
|
+
component: 'AnalyticsView'
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 3. Context-Specific Lazy Loading
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
const contextViews: ViewDefinition[] = [
|
|
139
|
+
// Approval view: bundled (critical path)
|
|
140
|
+
{
|
|
141
|
+
id: 'approval-view',
|
|
142
|
+
name: 'Approval View',
|
|
143
|
+
priority: 150,
|
|
144
|
+
criteria: {
|
|
145
|
+
recordType: 'lsp7-transfer',
|
|
146
|
+
context: 'approval'
|
|
147
|
+
},
|
|
148
|
+
frameworks: {
|
|
149
|
+
vue: {
|
|
150
|
+
loader: LoaderHelpers.vueComponent('./views/ApprovalView.vue'),
|
|
151
|
+
component: 'ApprovalView'
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
// Detail view: lazy (not critical)
|
|
157
|
+
{
|
|
158
|
+
id: 'detail-view',
|
|
159
|
+
name: 'Detail View',
|
|
160
|
+
priority: 100,
|
|
161
|
+
criteria: {
|
|
162
|
+
recordType: 'lsp7-transfer',
|
|
163
|
+
context: 'detail'
|
|
164
|
+
},
|
|
165
|
+
frameworks: {
|
|
166
|
+
vue: {
|
|
167
|
+
loader: LoaderHelpers.vueComponent(() => import('./views/DetailView.vue')),
|
|
168
|
+
component: 'DetailView'
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 4. Chain-Specific Lazy Loading
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
const chainViews: ViewDefinition[] = [
|
|
179
|
+
// Mainnet: bundled (primary network)
|
|
180
|
+
{
|
|
181
|
+
id: 'mainnet-view',
|
|
182
|
+
name: 'Mainnet View',
|
|
183
|
+
priority: 120,
|
|
184
|
+
criteria: {
|
|
185
|
+
recordType: 'special-transaction',
|
|
186
|
+
chainId: 42
|
|
187
|
+
},
|
|
188
|
+
frameworks: {
|
|
189
|
+
vue: {
|
|
190
|
+
loader: LoaderHelpers.vueComponent('./views/MainnetView.vue'),
|
|
191
|
+
component: 'MainnetView'
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
// Testnet: lazy (less common)
|
|
197
|
+
{
|
|
198
|
+
id: 'testnet-view',
|
|
199
|
+
name: 'Testnet View',
|
|
200
|
+
priority: 120,
|
|
201
|
+
criteria: {
|
|
202
|
+
recordType: 'special-transaction',
|
|
203
|
+
chainId: 4201
|
|
204
|
+
},
|
|
205
|
+
frameworks: {
|
|
206
|
+
vue: {
|
|
207
|
+
loader: LoaderHelpers.vueComponent(() => import('./views/TestnetView.vue')),
|
|
208
|
+
component: 'TestnetView'
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Advanced Patterns
|
|
216
|
+
|
|
217
|
+
### 1. Conditional Lazy Loading
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
function createViews(isDevelopment: boolean): ViewDefinition[] {
|
|
221
|
+
return [
|
|
222
|
+
{
|
|
223
|
+
id: 'debug-view',
|
|
224
|
+
name: 'Debug View',
|
|
225
|
+
priority: 200,
|
|
226
|
+
criteria: { recordType: 'debug' },
|
|
227
|
+
frameworks: {
|
|
228
|
+
vue: {
|
|
229
|
+
// Only bundle in development, lazy in production
|
|
230
|
+
loader: isDevelopment
|
|
231
|
+
? LoaderHelpers.vueComponent('./views/DebugView.vue')
|
|
232
|
+
: LoaderHelpers.vueComponent(() => import('./views/DebugView.vue')),
|
|
233
|
+
component: 'DebugView'
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 2. Route-Based Lazy Loading
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// App initialization
|
|
245
|
+
const registry = getGlobalRegistry()
|
|
246
|
+
|
|
247
|
+
// Register common views immediately
|
|
248
|
+
registry.registerMany(commonViews)
|
|
249
|
+
|
|
250
|
+
// Lazy register route-specific views
|
|
251
|
+
router.beforeEach(async (to, from, next) => {
|
|
252
|
+
if (to.path === '/transactions' && !transactionViewsLoaded) {
|
|
253
|
+
const transactionViews = await import('./views/transaction-views')
|
|
254
|
+
registry.registerMany(transactionViews.default)
|
|
255
|
+
transactionViewsLoaded = true
|
|
256
|
+
}
|
|
257
|
+
next()
|
|
258
|
+
})
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 3. Dynamic Import with Webpack Magic Comments
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
const optimizedViews: ViewDefinition[] = [
|
|
265
|
+
{
|
|
266
|
+
id: 'heavy-view',
|
|
267
|
+
name: 'Heavy View',
|
|
268
|
+
priority: 100,
|
|
269
|
+
criteria: { recordType: 'heavy' },
|
|
270
|
+
frameworks: {
|
|
271
|
+
vue: {
|
|
272
|
+
loader: LoaderHelpers.vueComponent(() => import(
|
|
273
|
+
/* webpackChunkName: "heavy-view" */
|
|
274
|
+
/* webpackPrefetch: true */
|
|
275
|
+
'./views/HeavyView.vue'
|
|
276
|
+
)),
|
|
277
|
+
component: 'HeavyView'
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Bundle Splitting Strategies
|
|
285
|
+
|
|
286
|
+
### Small Apps (< 100KB total)
|
|
287
|
+
**Bundle everything** - lazy loading overhead isn't worth it.
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
// Bundle all views
|
|
291
|
+
LoaderHelpers.vueComponent('./AllViews.vue')
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Medium Apps (100KB - 1MB)
|
|
295
|
+
**Lazy load rare views** - common views bundled.
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// Common: bundled
|
|
299
|
+
LoaderHelpers.vueComponent('./CommonView.vue')
|
|
300
|
+
|
|
301
|
+
// Rare: lazy
|
|
302
|
+
LoaderHelpers.vueComponent(() => import('./RareView.vue'))
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Large Apps (> 1MB)
|
|
306
|
+
**Lazy load everything except critical path**.
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
// Critical (approval flow): bundled
|
|
310
|
+
LoaderHelpers.vueComponent('./ApprovalView.vue')
|
|
311
|
+
|
|
312
|
+
// Everything else: lazy
|
|
313
|
+
LoaderHelpers.vueComponent(() => import('./DetailView.vue'))
|
|
314
|
+
LoaderHelpers.vueComponent(() => import('./HistoryView.vue'))
|
|
315
|
+
LoaderHelpers.vueComponent(() => import('./AnalyticsView.vue'))
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Custom Package with Lazy Loading
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
// @myorg/custom-views/src/registry/view-definitions.ts
|
|
322
|
+
import { LoaderHelpers } from '@lukso/transaction-view-headless'
|
|
323
|
+
import type { ViewDefinition } from '@lukso/transaction-view-headless'
|
|
324
|
+
|
|
325
|
+
export const customViews: ViewDefinition[] = [
|
|
326
|
+
{
|
|
327
|
+
id: 'custom-token-view',
|
|
328
|
+
name: 'Custom Token View',
|
|
329
|
+
priority: 130,
|
|
330
|
+
criteria: {
|
|
331
|
+
standard: 'CustomToken',
|
|
332
|
+
contractAddress: '0x123...'
|
|
333
|
+
},
|
|
334
|
+
frameworks: {
|
|
335
|
+
lit: {
|
|
336
|
+
loader: LoaderHelpers.litComponent('custom-token-view'),
|
|
337
|
+
component: 'custom-token-view'
|
|
338
|
+
},
|
|
339
|
+
vue: {
|
|
340
|
+
// Lazy loaded - only downloads when custom token is encountered
|
|
341
|
+
loader: LoaderHelpers.vueComponent(() => import('../views/vue/CustomTokenView.vue')),
|
|
342
|
+
component: 'CustomTokenView',
|
|
343
|
+
package: '@myorg/custom-views'
|
|
344
|
+
},
|
|
345
|
+
rn: {
|
|
346
|
+
// Lazy loaded for React Native
|
|
347
|
+
loader: LoaderHelpers.rnComponent(() => import('../views/rn/CustomTokenView.tsx')),
|
|
348
|
+
component: 'CustomTokenView',
|
|
349
|
+
package: '@myorg/custom-views'
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
]
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Performance Comparison
|
|
357
|
+
|
|
358
|
+
### Without Lazy Loading
|
|
359
|
+
```
|
|
360
|
+
Initial Bundle: 2.5 MB
|
|
361
|
+
- Common views: 500 KB
|
|
362
|
+
- Rare views: 2 MB ❌ (rarely used!)
|
|
363
|
+
|
|
364
|
+
Time to Interactive: 3.5s
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### With Lazy Loading
|
|
368
|
+
```
|
|
369
|
+
Initial Bundle: 500 KB
|
|
370
|
+
- Common views: 500 KB
|
|
371
|
+
|
|
372
|
+
Loaded on demand:
|
|
373
|
+
- Rare view 1: 300 KB (when needed)
|
|
374
|
+
- Rare view 2: 400 KB (when needed)
|
|
375
|
+
- etc.
|
|
376
|
+
|
|
377
|
+
Time to Interactive: 1.2s ✅ (66% faster!)
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## Best Practices
|
|
381
|
+
|
|
382
|
+
### 1. Bundle Critical Path, Lazy Load Everything Else
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// Approval flow (critical): bundle
|
|
386
|
+
✅ LoaderHelpers.vueComponent('./ApprovalView.vue')
|
|
387
|
+
|
|
388
|
+
// History view (not critical): lazy
|
|
389
|
+
✅ LoaderHelpers.vueComponent(() => import('./HistoryView.vue'))
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### 2. Use Webpack Magic Comments
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
LoaderHelpers.vueComponent(() => import(
|
|
396
|
+
/* webpackChunkName: "transaction-history" */
|
|
397
|
+
/* webpackPrefetch: true */ // Prefetch during idle time
|
|
398
|
+
'./HistoryView.vue'
|
|
399
|
+
))
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### 3. Group Related Views
|
|
403
|
+
|
|
404
|
+
```typescript
|
|
405
|
+
// Group LSP8 views in one chunk
|
|
406
|
+
LoaderHelpers.vueComponent(() => import(
|
|
407
|
+
/* webpackChunkName: "lsp8-views" */
|
|
408
|
+
'./views/lsp8/LSP8Transfer.vue'
|
|
409
|
+
))
|
|
410
|
+
|
|
411
|
+
LoaderHelpers.vueComponent(() => import(
|
|
412
|
+
/* webpackChunkName: "lsp8-views" */ // Same chunk name
|
|
413
|
+
'./views/lsp8/LSP8Mint.vue'
|
|
414
|
+
))
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 4. Measure Impact
|
|
418
|
+
|
|
419
|
+
```typescript
|
|
420
|
+
// Before lazy loading
|
|
421
|
+
console.time('initial-load')
|
|
422
|
+
import '@myorg/custom-views'
|
|
423
|
+
console.timeEnd('initial-load') // 2500ms
|
|
424
|
+
|
|
425
|
+
// After lazy loading
|
|
426
|
+
console.time('initial-load')
|
|
427
|
+
import '@myorg/custom-views/registry' // Only definitions, not components
|
|
428
|
+
console.timeEnd('initial-load') // 50ms ✅ (98% faster!)
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Migration Guide
|
|
432
|
+
|
|
433
|
+
### Before (Static Imports)
|
|
434
|
+
```typescript
|
|
435
|
+
// Old: Everything bundled
|
|
436
|
+
import LSP7View from './LSP7View.vue'
|
|
437
|
+
import LSP8View from './LSP8View.vue'
|
|
438
|
+
import RareView from './RareView.vue'
|
|
439
|
+
|
|
440
|
+
const views: ViewDefinition[] = [
|
|
441
|
+
{
|
|
442
|
+
id: 'lsp7-view',
|
|
443
|
+
frameworks: {
|
|
444
|
+
vue: {
|
|
445
|
+
loader: { type: 'static-import', path: './LSP7View.vue' },
|
|
446
|
+
component: 'LSP7View'
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
]
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### After (Lazy Loading)
|
|
454
|
+
```typescript
|
|
455
|
+
// New: Lazy loaded
|
|
456
|
+
const views: ViewDefinition[] = [
|
|
457
|
+
{
|
|
458
|
+
id: 'lsp7-view',
|
|
459
|
+
frameworks: {
|
|
460
|
+
vue: {
|
|
461
|
+
loader: LoaderHelpers.vueComponent(() => import('./LSP7View.vue')),
|
|
462
|
+
component: 'LSP7View'
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
]
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
## Troubleshooting
|
|
470
|
+
|
|
471
|
+
### Issue: Module not found
|
|
472
|
+
```
|
|
473
|
+
Error: Cannot find module './Component.vue'
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
**Solution:** Ensure path is relative to the file defining the loader:
|
|
477
|
+
```typescript
|
|
478
|
+
// ✅ Correct (relative to current file)
|
|
479
|
+
() => import('./views/Component.vue')
|
|
480
|
+
|
|
481
|
+
// ❌ Wrong (absolute path doesn't work in dynamic import)
|
|
482
|
+
() => import('/absolute/path/Component.vue')
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Issue: Loader not working
|
|
486
|
+
```
|
|
487
|
+
Error: Failed to load component
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
**Solution:** Ensure callback returns a Promise:
|
|
491
|
+
```typescript
|
|
492
|
+
// ✅ Correct
|
|
493
|
+
() => import('./Component.vue')
|
|
494
|
+
|
|
495
|
+
// ❌ Wrong (not a function)
|
|
496
|
+
'./Component.vue'
|
|
497
|
+
|
|
498
|
+
// ❌ Wrong (not returning Promise)
|
|
499
|
+
() => './Component.vue'
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Issue: TypeScript errors
|
|
503
|
+
|
|
504
|
+
**Solution:** Add proper types:
|
|
505
|
+
```typescript
|
|
506
|
+
import type { ViewDefinition } from '@lukso/transaction-view-headless'
|
|
507
|
+
|
|
508
|
+
const views: ViewDefinition[] = [
|
|
509
|
+
{
|
|
510
|
+
// TypeScript knows path can be string | (() => Promise<any>)
|
|
511
|
+
loader: LoaderHelpers.vueComponent(() => import('./Component.vue'))
|
|
512
|
+
}
|
|
513
|
+
]
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
## Summary
|
|
517
|
+
|
|
518
|
+
**Lazy loading views** dramatically improves app performance by:
|
|
519
|
+
1. Reducing initial bundle size (50-90% smaller)
|
|
520
|
+
2. Faster time to interactive (2-3x faster)
|
|
521
|
+
3. Loading components only when needed
|
|
522
|
+
4. Better code splitting and caching
|
|
523
|
+
|
|
524
|
+
**Use callbacks everywhere**:
|
|
525
|
+
```typescript
|
|
526
|
+
// ✅ Recommended
|
|
527
|
+
LoaderHelpers.vueComponent(() => import('./View.vue'))
|
|
528
|
+
LoaderHelpers.rnComponent(() => import('./View.tsx'))
|
|
529
|
+
|
|
530
|
+
// Only bundle if truly critical:
|
|
531
|
+
LoaderHelpers.vueComponent('./ApprovalView.vue')
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
This is the recommended pattern for all production apps!
|