@linagora/linid-im-front-corelib 0.0.5 → 0.0.7
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 +3 -3
- package/dist/core-lib.es.js +923 -852
- package/dist/core-lib.umd.js +9 -9
- package/dist/package.json +19 -14
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/types/src/index.d.ts +4 -0
- package/dist/types/src/services/httpClientService.d.ts +13 -0
- package/dist/types/src/services/linIdConfigurationService.d.ts +21 -0
- package/dist/types/src/stores/linIdConfigurationStore.d.ts +79 -0
- package/dist/types/src/types/linidConfiguration.d.ts +42 -0
- package/package.json +18 -13
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -83
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -90
- package/.github/ISSUE_TEMPLATE/question.yml +0 -31
- package/.github/ISSUE_TEMPLATE/security.yml +0 -69
- package/.github/actions/setup-node-pnpm/action.yml +0 -29
- package/.github/workflows/pull-request.yml +0 -147
- package/.github/workflows/release.yml +0 -90
- package/.prettierignore +0 -7
- package/.prettierrc.json +0 -5
- package/.vscode/extensions.json +0 -3
- package/.vscode/settings.json +0 -9
- package/CHANGELOG.md +0 -40
- package/CONTRIBUTING.md +0 -269
- package/COPYRIGHT +0 -23
- package/docs/components-plugin-zones.md +0 -168
- package/docs/helpers.md +0 -188
- package/docs/module-lifecycle.md +0 -717
- package/docs/types-and-interfaces.md +0 -92
- package/eslint.config.js +0 -136
- package/src/components/LinidZoneRenderer.vue +0 -77
- package/src/index.ts +0 -51
- package/src/lifecycle/skeleton.ts +0 -147
- package/src/services/federationService.ts +0 -44
- package/src/stores/linidZoneStore.ts +0 -62
- package/src/types/linidZone.ts +0 -48
- package/src/types/module.ts +0 -96
- package/src/types/moduleLifecycle.ts +0 -154
- package/tests/unit/components/LinidZoneRenderer.spec.js +0 -135
- package/tests/unit/lifecycle/skeleton.spec.js +0 -138
- package/tests/unit/services/federationService.spec.js +0 -146
- package/tests/unit/stores/linidZoneStore.spec.js +0 -94
- package/tsconfig.json +0 -14
- package/tsconfig.lib.json +0 -20
- package/tsconfig.node.json +0 -9
- package/tsconfig.spec.json +0 -16
- package/vite.config.ts +0 -37
- package/vitest.config.ts +0 -19
package/docs/module-lifecycle.md
DELETED
|
@@ -1,717 +0,0 @@
|
|
|
1
|
-
# Module Lifecycle System
|
|
2
|
-
|
|
3
|
-
The module lifecycle system provides a standardized way for business modules to initialize themselves in the host application.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
The lifecycle consists of five phases that are executed in sequence for all modules:
|
|
8
|
-
|
|
9
|
-
# Module Lifecycle System
|
|
10
|
-
|
|
11
|
-
The module lifecycle system provides a standardized way for business modules to initialize themselves in the host application.
|
|
12
|
-
|
|
13
|
-
## Overview
|
|
14
|
-
|
|
15
|
-
The lifecycle consists of five phases that are executed in sequence for all modules:
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
Setup → Configure → Initialize → Ready → Post-Init
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Each phase has a specific purpose and is executed for **all modules** before moving to the next phase.
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## Lifecycle Phases
|
|
26
|
-
|
|
27
|
-
### 1. Setup Phase
|
|
28
|
-
|
|
29
|
-
**Purpose:** Validate dependencies and prepare the module
|
|
30
|
-
|
|
31
|
-
**When executed:** First phase, after the module is loaded via Module Federation
|
|
32
|
-
|
|
33
|
-
**Use cases:**
|
|
34
|
-
|
|
35
|
-
- Check if required dependencies are available
|
|
36
|
-
- Validate environment
|
|
37
|
-
- Prepare internal state
|
|
38
|
-
- Check Vue version compatibility
|
|
39
|
-
|
|
40
|
-
**Hook signature:**
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
async setup(): Promise<ModuleLifecycleResult>
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Implementation example:**
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
async setup(): Promise<ModuleLifecycleResult> {
|
|
50
|
-
if (!app) {
|
|
51
|
-
return {
|
|
52
|
-
success: false,
|
|
53
|
-
error: 'Vue app instance not available'
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
return { success: true };
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
### 2. Configure Phase
|
|
63
|
-
|
|
64
|
-
**Purpose:** Receive and validate host configuration
|
|
65
|
-
|
|
66
|
-
**When executed:** After setup, before initialization
|
|
67
|
-
|
|
68
|
-
**Use cases:**
|
|
69
|
-
|
|
70
|
-
- Receive configuration from host (`module-<name>.json`)
|
|
71
|
-
- Validate required configuration fields
|
|
72
|
-
- Store configuration for later use
|
|
73
|
-
- Apply configuration settings
|
|
74
|
-
|
|
75
|
-
**Hook signature:**
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
async configure(config: ModuleHostConfig): Promise<ModuleLifecycleResult>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
**Implementation example:**
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
async configure(
|
|
85
|
-
config: ModuleHostConfig
|
|
86
|
-
): Promise<ModuleLifecycleResult> {
|
|
87
|
-
if (!config.id) {
|
|
88
|
-
return {
|
|
89
|
-
success: false,
|
|
90
|
-
error: 'Missing module ID in configuration'
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return { success: true };
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
### 3. Initialize Phase
|
|
101
|
-
|
|
102
|
-
**Purpose:** Register stores and initialize resources
|
|
103
|
-
|
|
104
|
-
**When executed:** After configuration
|
|
105
|
-
|
|
106
|
-
**Use cases:**
|
|
107
|
-
|
|
108
|
-
- Register Pinia stores
|
|
109
|
-
- Set up event listeners
|
|
110
|
-
- Initialize module-specific resources
|
|
111
|
-
- Prepare data structures
|
|
112
|
-
|
|
113
|
-
**Hook signature:**
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
async initialize(): Promise<ModuleLifecycleResult>
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
**Implementation example:**
|
|
120
|
-
|
|
121
|
-
```typescript
|
|
122
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
123
|
-
// Register Pinia store
|
|
124
|
-
const pinia = app.config.globalProperties.$pinia;
|
|
125
|
-
pinia.use(myStorePlugin);
|
|
126
|
-
|
|
127
|
-
// Initialize module resources
|
|
128
|
-
await this.loadInitialData();
|
|
129
|
-
|
|
130
|
-
return {
|
|
131
|
-
success: true,
|
|
132
|
-
metadata: { storesRegistered: 1 }
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
---
|
|
138
|
-
|
|
139
|
-
### 4. Ready Phase
|
|
140
|
-
|
|
141
|
-
**Purpose:** Signal that the module is ready for use
|
|
142
|
-
|
|
143
|
-
**When executed:** After all modules are initialized
|
|
144
|
-
|
|
145
|
-
**Use cases:**
|
|
146
|
-
|
|
147
|
-
- Perform final checks
|
|
148
|
-
- Emit ready events
|
|
149
|
-
- Log readiness status
|
|
150
|
-
|
|
151
|
-
**Hook signature:**
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
async ready(): Promise<ModuleLifecycleResult>
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
**Implementation example:**
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
async ready(): Promise<ModuleLifecycleResult> {
|
|
161
|
-
console.log(`Module ${this.name} v${this.version} is ready!`);
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
success: true,
|
|
165
|
-
metadata: { startTime: Date.now() }
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
---
|
|
171
|
-
|
|
172
|
-
### 5. Post-Init Phase
|
|
173
|
-
|
|
174
|
-
**Purpose:** Cross-module integrations and final setup
|
|
175
|
-
|
|
176
|
-
**When executed:** After all modules are ready
|
|
177
|
-
|
|
178
|
-
**Use cases:**
|
|
179
|
-
|
|
180
|
-
- Integrate with other modules
|
|
181
|
-
- Set up cross-module communication
|
|
182
|
-
- Perform final setup that requires all modules to be ready
|
|
183
|
-
|
|
184
|
-
**Hook signature:**
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
async postInit(): Promise<ModuleLifecycleResult>
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**Implementation example:**
|
|
191
|
-
|
|
192
|
-
```typescript
|
|
193
|
-
async postInit(): Promise<ModuleLifecycleResult> {
|
|
194
|
-
// Access other modules from host's module registry
|
|
195
|
-
// Set up cross-module event listeners
|
|
196
|
-
// Perform integrations
|
|
197
|
-
|
|
198
|
-
return { success: true };
|
|
199
|
-
}
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## Result Object
|
|
205
|
-
|
|
206
|
-
All lifecycle hooks must return a `ModuleLifecycleResult`:
|
|
207
|
-
|
|
208
|
-
```typescript
|
|
209
|
-
interface ModuleLifecycleResult {
|
|
210
|
-
/**
|
|
211
|
-
* Whether the phase completed successfully.
|
|
212
|
-
* If false, the error is logged but the module continues through remaining phases.
|
|
213
|
-
*/
|
|
214
|
-
success: boolean;
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Error message if the phase failed.
|
|
218
|
-
*/
|
|
219
|
-
error?: string;
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Additional metadata from the phase (for debugging).
|
|
223
|
-
*/
|
|
224
|
-
metadata?: Record<string, unknown>;
|
|
225
|
-
}
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
### Success Result
|
|
229
|
-
|
|
230
|
-
```typescript
|
|
231
|
-
return { success: true };
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
### Success with Metadata
|
|
235
|
-
|
|
236
|
-
```typescript
|
|
237
|
-
return {
|
|
238
|
-
success: true,
|
|
239
|
-
metadata: {
|
|
240
|
-
storesRegistered: 2,
|
|
241
|
-
dataLoaded: true,
|
|
242
|
-
},
|
|
243
|
-
};
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
### Failure Result
|
|
247
|
-
|
|
248
|
-
```typescript
|
|
249
|
-
return {
|
|
250
|
-
success: false,
|
|
251
|
-
error: 'Missing required configuration',
|
|
252
|
-
};
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
---
|
|
256
|
-
|
|
257
|
-
## Implementing a Module
|
|
258
|
-
|
|
259
|
-
### Option 1: Extending BasicRemoteModule (Recommended)
|
|
260
|
-
|
|
261
|
-
The corelib provides a `BasicRemoteModule` class with default implementations for all hooks:
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
import { BasicRemoteModule } from '@linagora/linid-im-front-corelib';
|
|
265
|
-
import type { ModuleLifecycleResult } from '@linagora/linid-im-front-corelib';
|
|
266
|
-
import type { App } from 'vue';
|
|
267
|
-
|
|
268
|
-
class MyModule extends BasicRemoteModule {
|
|
269
|
-
constructor() {
|
|
270
|
-
super('my-module', 'My Business Module', '1.0.0', 'Description');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Override only the hooks you need
|
|
274
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
275
|
-
// do something
|
|
276
|
-
|
|
277
|
-
return { success: true };
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export default new MyModule();
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
**Advantages:**
|
|
285
|
-
|
|
286
|
-
- ✅ All hooks have default implementations (return success)
|
|
287
|
-
- ✅ Override only what you need
|
|
288
|
-
- ✅ Object-oriented design
|
|
289
|
-
- ✅ Follows SOLID principles
|
|
290
|
-
- ✅ Easy to extend and maintain
|
|
291
|
-
|
|
292
|
-
---
|
|
293
|
-
|
|
294
|
-
### Option 2: Implementing RemoteModule Interface
|
|
295
|
-
|
|
296
|
-
Implement the `RemoteModule` interface directly for full control:
|
|
297
|
-
|
|
298
|
-
```typescript
|
|
299
|
-
import type {
|
|
300
|
-
RemoteModule,
|
|
301
|
-
ModuleLifecycleResult,
|
|
302
|
-
ModuleHostConfig,
|
|
303
|
-
} from '@linagora/linid-im-front-corelib';
|
|
304
|
-
import type { App } from 'vue';
|
|
305
|
-
|
|
306
|
-
class MyModule implements RemoteModule {
|
|
307
|
-
id = 'my-module';
|
|
308
|
-
name = 'My Business Module';
|
|
309
|
-
version = '1.0.0';
|
|
310
|
-
description = 'Description of what the module does';
|
|
311
|
-
|
|
312
|
-
async setup(): Promise<ModuleLifecycleResult> {
|
|
313
|
-
// Validate dependencies
|
|
314
|
-
return { success: true };
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
async configure(
|
|
318
|
-
config: ModuleHostConfig
|
|
319
|
-
): Promise<ModuleLifecycleResult> {
|
|
320
|
-
// Apply configuration
|
|
321
|
-
if (!config.id) {
|
|
322
|
-
return { success: false, error: 'Missing module ID' };
|
|
323
|
-
}
|
|
324
|
-
return { success: true };
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
328
|
-
// do something
|
|
329
|
-
return { success: true };
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
async ready(): Promise<ModuleLifecycleResult> {
|
|
333
|
-
// do something
|
|
334
|
-
return { success: true };
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
async postInit(): Promise<ModuleLifecycleResult> {
|
|
338
|
-
// Cross-module integrations
|
|
339
|
-
return { success: true };
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
export default new MyModule();
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
**Advantages:**
|
|
347
|
-
|
|
348
|
-
- ✅ Full control over implementation
|
|
349
|
-
- ✅ Implement only needed hooks
|
|
350
|
-
- ✅ Type-safe with TypeScript
|
|
351
|
-
- ✅ Clean, explicit code
|
|
352
|
-
|
|
353
|
-
---
|
|
354
|
-
|
|
355
|
-
### Module Federation Configuration
|
|
356
|
-
|
|
357
|
-
Expose the lifecycle in your module's `vite.config.ts`:
|
|
358
|
-
|
|
359
|
-
```typescript
|
|
360
|
-
import { defineConfig } from 'vite';
|
|
361
|
-
import federation from '@originjs/vite-plugin-federation';
|
|
362
|
-
|
|
363
|
-
export default defineConfig({
|
|
364
|
-
plugins: [
|
|
365
|
-
federation({
|
|
366
|
-
name: 'myBusinessModule',
|
|
367
|
-
filename: 'remoteEntry.js',
|
|
368
|
-
exposes: {
|
|
369
|
-
'./lifecycle': './src/lifecycle.ts', // Required for business modules
|
|
370
|
-
'./MyComponent': './src/components/MyComponent.vue',
|
|
371
|
-
},
|
|
372
|
-
}),
|
|
373
|
-
],
|
|
374
|
-
});
|
|
375
|
-
```
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
## Best Practices
|
|
380
|
-
|
|
381
|
-
### 1. Keep Phases Focused
|
|
382
|
-
|
|
383
|
-
Each phase should have a single, clear responsibility.
|
|
384
|
-
|
|
385
|
-
✅ **Good:**
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
389
|
-
return { success: true };
|
|
390
|
-
}
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
❌ **Bad:**
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
397
|
-
await fetchUserData(); // Should be in ready or postInit
|
|
398
|
-
integrateWithOtherModule(); // Should be in postInit
|
|
399
|
-
return { success: true };
|
|
400
|
-
}
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
---
|
|
404
|
-
|
|
405
|
-
### 2. Always Return a Valid Result
|
|
406
|
-
|
|
407
|
-
Never return `undefined` or forget the return statement.
|
|
408
|
-
|
|
409
|
-
✅ **Good:**
|
|
410
|
-
|
|
411
|
-
```typescript
|
|
412
|
-
return { success: true };
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
✅ **Good:**
|
|
416
|
-
|
|
417
|
-
```typescript
|
|
418
|
-
return {
|
|
419
|
-
success: false,
|
|
420
|
-
error: 'Missing required configuration',
|
|
421
|
-
};
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
❌ **Bad:**
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
return; // Invalid, returns undefined
|
|
428
|
-
```
|
|
429
|
-
|
|
430
|
-
---
|
|
431
|
-
|
|
432
|
-
### 3. Use Metadata for Debugging
|
|
433
|
-
|
|
434
|
-
Provide useful debugging information in the metadata.
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
return {
|
|
438
|
-
success: true,
|
|
439
|
-
metadata: {
|
|
440
|
-
storesRegistered: 2,
|
|
441
|
-
routesRegistered: 3,
|
|
442
|
-
duration: Date.now() - startTime,
|
|
443
|
-
},
|
|
444
|
-
};
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
---
|
|
448
|
-
|
|
449
|
-
### 4. Fail Fast in Setup
|
|
450
|
-
|
|
451
|
-
Validate prerequisites early in the Setup phase.
|
|
452
|
-
|
|
453
|
-
```typescript
|
|
454
|
-
async setup(): Promise<ModuleLifecycleResult> {
|
|
455
|
-
if (!window.someRequiredAPI) {
|
|
456
|
-
return {
|
|
457
|
-
success: false,
|
|
458
|
-
error: 'Required API not available'
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
if (!app) {
|
|
463
|
-
return {
|
|
464
|
-
success: false,
|
|
465
|
-
error: 'Vue app instance not available'
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
return { success: true };
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
---
|
|
474
|
-
|
|
475
|
-
### 5. Don't Throw Errors
|
|
476
|
-
|
|
477
|
-
Return failure results instead of throwing errors.
|
|
478
|
-
|
|
479
|
-
✅ **Good:**
|
|
480
|
-
|
|
481
|
-
```typescript
|
|
482
|
-
if (!config.id) {
|
|
483
|
-
return { success: false, error: 'Missing module ID' };
|
|
484
|
-
}
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
❌ **Bad:**
|
|
488
|
-
|
|
489
|
-
```typescript
|
|
490
|
-
if (!config.id) {
|
|
491
|
-
throw new Error('Missing module ID'); // Will be caught by host but not clean
|
|
492
|
-
}
|
|
493
|
-
```
|
|
494
|
-
|
|
495
|
-
**Why:** Thrown errors are caught by the host and converted to failure results, but explicit returns are clearer and follow the expected pattern.
|
|
496
|
-
|
|
497
|
-
---
|
|
498
|
-
|
|
499
|
-
### 6. Implement Only What You Need
|
|
500
|
-
|
|
501
|
-
All lifecycle hooks are optional. Don't implement hooks your module doesn't need.
|
|
502
|
-
|
|
503
|
-
```typescript
|
|
504
|
-
class SimpleModule extends BasicRemoteModule {
|
|
505
|
-
constructor() {
|
|
506
|
-
super('simple-module', 'Simple Module', '1.0.0');
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
510
|
-
return { success: true };
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// No need for setup, configure, ready, or postInit
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
export default new SimpleModule();
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
---
|
|
520
|
-
|
|
521
|
-
## Error Handling
|
|
522
|
-
|
|
523
|
-
### Module Fails to Load
|
|
524
|
-
|
|
525
|
-
If a module fails to load via Module Federation, the host will log an error:
|
|
526
|
-
|
|
527
|
-
```
|
|
528
|
-
[Module Lifecycle] Failed to load module myBusinessModule/lifecycle: <error>
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
**Consequences:**
|
|
532
|
-
|
|
533
|
-
- Module is not added to the registry
|
|
534
|
-
- Module does not participate in lifecycle phases
|
|
535
|
-
- Other modules continue normally
|
|
536
|
-
|
|
537
|
-
---
|
|
538
|
-
|
|
539
|
-
### Phase Execution Fails
|
|
540
|
-
|
|
541
|
-
If a lifecycle phase returns `success: false` or throws an error:
|
|
542
|
-
|
|
543
|
-
```
|
|
544
|
-
[Module Lifecycle] my-module: Error in initialize phase: <error>
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
**Consequences:**
|
|
548
|
-
|
|
549
|
-
- Error is logged by the host
|
|
550
|
-
- Module continues through remaining phases
|
|
551
|
-
- Other modules are not affected
|
|
552
|
-
|
|
553
|
-
---
|
|
554
|
-
|
|
555
|
-
### Invalid Phase Result
|
|
556
|
-
|
|
557
|
-
If a lifecycle hook returns an invalid result (not a `ModuleLifecycleResult` object):
|
|
558
|
-
|
|
559
|
-
```
|
|
560
|
-
[Module Lifecycle] my-module: Phase setup returned invalid result, treating as success
|
|
561
|
-
```
|
|
562
|
-
|
|
563
|
-
**Consequences:**
|
|
564
|
-
|
|
565
|
-
- Host treats the phase as successful
|
|
566
|
-
- Module continues through remaining phases
|
|
567
|
-
- Warning is logged for debugging
|
|
568
|
-
|
|
569
|
-
---
|
|
570
|
-
|
|
571
|
-
## Execution Sequence
|
|
572
|
-
|
|
573
|
-
The host executes lifecycle phases in this order:
|
|
574
|
-
|
|
575
|
-
```
|
|
576
|
-
Host Application
|
|
577
|
-
│
|
|
578
|
-
├─ 1. Load modules.json (get list of modules to load)
|
|
579
|
-
│
|
|
580
|
-
├─ 2. For each module in modules.json:
|
|
581
|
-
│ ├─ Load module-<name>.json configuration
|
|
582
|
-
│ └─ Load module via Module Federation (remoteName/lifecycle)
|
|
583
|
-
│
|
|
584
|
-
├─ 3. Phase 1: Setup (all modules in parallel)
|
|
585
|
-
│ ├─ module-A.setup(app)
|
|
586
|
-
│ ├─ module-B.setup(app)
|
|
587
|
-
│ └─ module-C.setup(app)
|
|
588
|
-
│
|
|
589
|
-
├─ 4. Phase 2: Configure (all modules in parallel)
|
|
590
|
-
│ ├─ module-A.configure(app, configA)
|
|
591
|
-
│ ├─ module-B.configure(app, configB)
|
|
592
|
-
│ └─ module-C.configure(app, configC)
|
|
593
|
-
│
|
|
594
|
-
├─ 5. Phase 3: Initialize (all modules in parallel)
|
|
595
|
-
│ ├─ module-A.initialize(app)
|
|
596
|
-
│ ├─ module-B.initialize(app)
|
|
597
|
-
│ └─ module-C.initialize(app)
|
|
598
|
-
│
|
|
599
|
-
├─ 6. Phase 4: Ready (all modules in parallel)
|
|
600
|
-
│ ├─ module-A.ready(app)
|
|
601
|
-
│ ├─ module-B.ready(app)
|
|
602
|
-
│ └─ module-C.ready(app)
|
|
603
|
-
│
|
|
604
|
-
└─ 7. Phase 5: Post-Init (all modules in parallel)
|
|
605
|
-
├─ module-A.postInit(app)
|
|
606
|
-
├─ module-B.postInit(app)
|
|
607
|
-
└─ module-C.postInit(app)
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
**Key points:**
|
|
611
|
-
|
|
612
|
-
- All modules complete one phase before moving to the next
|
|
613
|
-
- Phases execute in parallel for all modules (using `Promise.allSettled`)
|
|
614
|
-
- Failure in one module doesn't block others
|
|
615
|
-
|
|
616
|
-
---
|
|
617
|
-
|
|
618
|
-
## Integration with Host
|
|
619
|
-
|
|
620
|
-
### Host Responsibilities
|
|
621
|
-
|
|
622
|
-
The host application is responsible for:
|
|
623
|
-
|
|
624
|
-
1. ✅ Loading module configurations from `modules.json`
|
|
625
|
-
2. ✅ Loading each module's configuration file (`module-<name>.json`)
|
|
626
|
-
3. ✅ Loading modules via Module Federation
|
|
627
|
-
4. ✅ Executing each lifecycle phase in sequence for all modules
|
|
628
|
-
5. ✅ Handling errors and logging
|
|
629
|
-
6. ✅ Providing the Vue `app` instance to modules
|
|
630
|
-
|
|
631
|
-
### Module Responsibilities
|
|
632
|
-
|
|
633
|
-
Business modules are responsible for:
|
|
634
|
-
|
|
635
|
-
1. ✅ Exposing `./lifecycle` in Module Federation config
|
|
636
|
-
2. ✅ Implementing the `RemoteModule` interface (or extending `BasicRemoteModule`)
|
|
637
|
-
3. ✅ Returning valid `ModuleLifecycleResult` from all hooks
|
|
638
|
-
4. ✅ Handling their own errors gracefully
|
|
639
|
-
5. ✅ Using the provided `app` instance correctly
|
|
640
|
-
|
|
641
|
-
---
|
|
642
|
-
|
|
643
|
-
## Future Enhancements
|
|
644
|
-
|
|
645
|
-
The following features are planned for future versions:
|
|
646
|
-
|
|
647
|
-
### Router Integration
|
|
648
|
-
|
|
649
|
-
Add direct router access for route registration:
|
|
650
|
-
|
|
651
|
-
```typescript
|
|
652
|
-
async initialize(): Promise<ModuleLifecycleResult> {
|
|
653
|
-
return { success: true };
|
|
654
|
-
}
|
|
655
|
-
```
|
|
656
|
-
|
|
657
|
-
### Zone System
|
|
658
|
-
|
|
659
|
-
Allow modules to inject components into named zones in the UI.
|
|
660
|
-
|
|
661
|
-
### Module Dependencies
|
|
662
|
-
|
|
663
|
-
Declare and validate inter-module dependencies:
|
|
664
|
-
|
|
665
|
-
```typescript
|
|
666
|
-
class MyModule extends BasicRemoteModule {
|
|
667
|
-
dependencies = ['core-module', 'auth-module'];
|
|
668
|
-
|
|
669
|
-
// ...
|
|
670
|
-
}
|
|
671
|
-
```
|
|
672
|
-
|
|
673
|
-
### Lazy Loading
|
|
674
|
-
|
|
675
|
-
Support for lazy-loaded module features that load on demand.
|
|
676
|
-
|
|
677
|
-
---
|
|
678
|
-
|
|
679
|
-
## Troubleshooting
|
|
680
|
-
|
|
681
|
-
### Module Not Loading
|
|
682
|
-
|
|
683
|
-
**Problem:** Module doesn't appear in lifecycle logs
|
|
684
|
-
|
|
685
|
-
**Solutions:**
|
|
686
|
-
|
|
687
|
-
1. Check module is listed in host's `modules.json`
|
|
688
|
-
2. Verify config file exists: `module-<name>.json`
|
|
689
|
-
3. Check Module Federation remote is registered in `remotes.json`
|
|
690
|
-
4. Verify module exposes `./lifecycle` in its Module Federation config
|
|
691
|
-
5. Check browser console for loading errors
|
|
692
|
-
|
|
693
|
-
---
|
|
694
|
-
|
|
695
|
-
### Lifecycle Hook Not Called
|
|
696
|
-
|
|
697
|
-
**Problem:** A specific lifecycle hook is not being called
|
|
698
|
-
|
|
699
|
-
**Solutions:**
|
|
700
|
-
|
|
701
|
-
1. Verify the hook is implemented and exported
|
|
702
|
-
2. Check the hook signature matches the interface
|
|
703
|
-
3. Ensure the hook is `async` and returns a `Promise<ModuleLifecycleResult>`
|
|
704
|
-
4. Check browser console for `[Module Lifecycle]` logs
|
|
705
|
-
|
|
706
|
-
---
|
|
707
|
-
|
|
708
|
-
### Configuration Not Received
|
|
709
|
-
|
|
710
|
-
**Problem:** Module's `configure` receives unexpected configuration
|
|
711
|
-
|
|
712
|
-
**Solutions:**
|
|
713
|
-
|
|
714
|
-
1. Verify module's `id` matches the `id` in host config
|
|
715
|
-
2. Check the config file path: `module-<module-name>.json`
|
|
716
|
-
3. Validate JSON syntax in config file
|
|
717
|
-
4. Check browser network tab for config file fetch (404?)
|