There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Lazy loading components | ||
|
||
## Summary | ||
|
||
Allow to lazy load components in runtime and render them as usual dynamic components. | ||
|
||
## Motivation | ||
|
||
Currently Orchestrator supports components to be provided via DI which limits it to build-time mostly. | ||
However it is benefitial to be able to load components on demand whenewer they are required to be rendered in the UI to reduce initial bundle size of the application. | ||
|
||
## Detailed Explanation | ||
|
||
To support lazy loading usecase the following changes have to be done: | ||
|
||
1. Allow to register dynamic components by providing a function that returns Promise of an actual component | ||
2. Adjust `orc-render-item` component to await for a lazy component to be loaded before rendering | ||
3. Allow to add component registries at runtime via `ComponentLocatorService` service so that custom lazy loading techniques may be implemented | ||
|
||
## Rationale and Alternatives | ||
|
||
The most simplest version for lazy loading would be to just implement item #3 from the section above and let devs to implement custom lazy loading components, however this will make a simple usecase harder to implment and different projects may have different implementations of the same problem - making them less interoperable between each other which is not ideal. | ||
|
||
## Implementation | ||
|
||
1. Update type definitions of `ComponentMap` and `ComponentRegistry` to support lazy loading by adding function signature that returns the same type it currently holds: | ||
|
||
```ts | ||
export type LazyComponentLoader<T extends Type<any> = DefaultDynamicComponent> = | ||
() => Promise<T>; | ||
|
||
export type ComponentOrLoader<T extends Type<any> = DefaultDynamicComponent> = | ||
| T | ||
| LazyComponentLoader<T>; | ||
|
||
export interface ComponentMap<T extends Type<any> = DefaultDynamicComponent> { | ||
[k: string]: ComponentOrLoader<T>; | ||
} | ||
|
||
export type ComponentRegistry<T extends Type<any> = DefaultDynamicComponent> = | ||
| ComponentOrLoader<T>[] | ||
| ComponentMap<T>; | ||
``` | ||
|
||
Update `ComponentLocatorService` to handle lazy component signatures: | ||
|
||
```ts | ||
class ComponentLocatorService { | ||
resolve<T, C = GetOrchestratorDynamicComponentConfig<T>>( | ||
component: string | OrchestratorDynamicComponentType<C>, | ||
): Promise<OrchestratorDynamicComponentType<C>> | undefined; | ||
} | ||
``` | ||
|
||
Method `resolve` MUST perform the following actions: | ||
|
||
- Check if the component map has entry for requested component | ||
- If NOT found - eeturn `undefined` | ||
- Check if the component map has lazy loader of the component | ||
- If true - execute lazy loader and return it's promise | ||
- Once resolved - replace lazy loader in the component map with a loaded component | ||
- If rejected - throw an error with details about which component failed to load and original error reason using `ErrorStrategy.handle()` API | ||
- Othrwise return component from the component map as-is | ||
|
||
2. Update `orc-render-item`: | ||
|
||
1. Wait for a component to be resolved from `ComponentLocatorService` | ||
2. Resolve config for a loaded component | ||
3. Render loaded component | ||
|
||
3. Update `ComponentLocatorService` to allow registering new components and expose all loaded/registered components: | ||
|
||
```ts | ||
class ComponentLocatorService { | ||
+registerComponent(component: ComponentOrLoader): void; | ||
+getComponentNames(): Observable<string[]>; | ||
+getLoadedComponents(): Observable<OrchestratorDynamicComponentType[]>; | ||
} | ||
``` | ||
|
||
Method `registerComponent` MUST perform the following actions: | ||
|
||
- Extend currently registered component map | ||
|
||
We specifically have 2 separate methods for getting components which are Observables so they can update whenever a new component is registered/loaded: | ||
|
||
- component names that are registered/loaded `getComponentNames` | ||
- already loaded components `getLoadedComponents` | ||
|
||
## Unresolved Questions and Bikeshedding | ||
|
||
Open questions: | ||
|
||
- What should be/not be rendered while a component is being loaded? | ||
For example we can have optional InjectionToken that can provide a component for rendering. | ||
- Should we provide a way for custom loader strategy ie. custom service? |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Lazy loading components #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Uh oh!
There was an error while loading. Please reload this page.
Lazy loading components #5
Changes from all commits
0414bfd
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.