-
-
Notifications
You must be signed in to change notification settings - Fork 235
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
feat: add bridgeHook plugin system to support lifecycyle in bridge #2992
base: main
Are you sure you want to change the base?
Conversation
…universe into feat/isolated-monitor
🦋 Changeset detectedLatest commit: dade92f The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for module-federation-docs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
The core changes in this pull request introduce a new "bridgeHook" plugin system to the module-federation bridge, allowing for better support of lifecycle hooks and more flexibility in integrating different scenes with the bridge capability.
The key changes include:
- Addition of a new plugin system called "bridgeHook" that provides lifecycle hooks such as "beforeBridgeRender", "afterBridgeRender", "beforeBridgeDestroy", and "afterBridgeDestroy". These hooks can be used to extend the functionality of the bridge and handle more diverse scenarios.
- Updates to various components, including
create.tsx
,provider.tsx
,remote/index.tsx
,router-v5.tsx
,router.tsx
, and their Vue3 counterparts, to integrate the new bridgeHook plugin system. - Introduction of new utility functions like
getModuleName
andgetRootDomDefaultClassName
to improve module name handling and CSS class generation. - Refactoring of the
SnapshotHandler
class to separate remote and global snapshot handling and add a newafterLoadSnapshot
hook. - Standardization of remote information representation through the new
RemoteInfoCommon
interface.
These changes aim to enhance the module-federation bridge's capabilities, allowing for more flexibility and support for different use cases when integrating various scenes with the bridge.
File Summaries
File | Summary |
---|---|
packages/bridge/bridge-react/src/create.tsx | The code changes introduce a new plugin system to support lifecycle hooks in the module-federation bridge, allowing for more flexibility and support for different use cases. The changes include the addition of an ErrorBoundary component and updates to the ProviderParams type to accommodate the new plugin system. |
packages/bridge/bridge-react/src/provider.tsx | The code changes introduce a new plugin system called "bridgeHook" to support lifecycle hooks in the module-federation bridge. This allows for more flexibility and customization when integrating different scenes with the bridge capability. The changes include adding new lifecycle hooks such as "beforeBridgeRender", "afterBridgeRender", "beforeBridgeDestroy", and "afterBridgeDestroy" that can be used to extend the functionality of the bridge. |
packages/bridge/bridge-react/src/remote/index.tsx | The code changes introduce a new plugin system called "bridgeHook" to support lifecycle hooks in the module-deferation bridge. This allows for more flexibility and support for different use cases when working with the bridge capability. |
packages/bridge/bridge-react/src/router-v5.tsx | The code changes introduce a new plugin system for the bridge-react library, allowing for the addition of lifecycle hooks to support more use cases within the module-deferation bridge. The changes focus on integrating the new bridgeHook plugin system into the existing router-v5 module, enabling developers to leverage lifecycle hooks in their bridge-based applications. |
packages/bridge/bridge-react/src/router.tsx | The changes in this file introduce a new feature to support lifecycle hooks in the module-deferation bridge, allowing for more scene support with bridge capability. The key modification is the addition of a new parameter, basename , to the createBrowserRouter function, which now defaults to the routerContextProps.basename or the router?.basename value. |
packages/bridge/bridge-react/src/utils.ts | The code changes introduce two new utility functions: getModuleName and getRootDomDefaultClassName . The getModuleName function extracts the module name from a given module ID, separating the module name from the detailed module path. The getRootDomDefaultClassName function generates a default CSS class name for the root component of a module based on the module name. |
packages/bridge/vue3-bridge/src/create.ts | The changes introduce a new plugin system for the module-deferation bridge, allowing for the support of lifecycle hooks to enable more scene-specific functionality. The key modifications include adding the useRoute function from vue-router and updating the import order to improve readability. |
packages/bridge/vue3-bridge/src/provider.ts | The code changes introduce a new plugin system called "bridgeHook" to the module-deferation bridge, allowing for the support of lifecycle hooks. This enables more flexibility and customization in the bridge's behavior, such as executing custom logic before and after rendering or destroying the bridge component. |
packages/bridge/vue3-bridge/src/remoteApp.tsx | The code changes introduce a new bridgeHook plugin system to support lifecycle events in the module-federation bridge. The changes include adding hooks for before the bridge component is rendered and after it is destroyed, allowing for additional functionality to be added to the bridge lifecycle. |
packages/runtime/src/core.ts | The code changes introduce a new bridgeHook plugin system to the FederationHost class, which allows for the addition of lifecycle hooks to support more scenarios with the bridge capability. The new plugin system includes four hooks: beforeBridgeRender , afterBridgeRender , beforeBridgeDestroy , and afterBridgeDestroy , which can be used to extend the functionality of the bridge. |
packages/runtime/src/embedded.ts | The code changes introduce a new bridgeHook property to the FederationHost class, which allows for the support of lifecycle hooks in the module-deferation bridge. This enhancement enables the handling of more diverse scenarios that require bridge capabilities. |
packages/runtime/src/module/index.ts | The code changes introduce a new feature to support lifecycle hooks in the module-deferation bridge, allowing for better support of different scenarios with bridge capability. The key modifications include adding a new utility function processModuleAlias to ensure consistent module name formatting, and updating the wraperFactory method to use the processed module name instead of the raw exposed name. |
packages/runtime/src/plugins/snapshot/SnapshotHandler.ts | The code changes introduce a new afterLoadSnapshot hook in the SnapshotHandler class, which is called after a remote snapshot has been loaded. This allows for additional processing or handling of the loaded snapshot data. The changes also refactor the existing snapshot loading logic to separate the remote snapshot and global snapshot handling, and emit the afterLoadSnapshot hook at the end of the loadSnapshot method. |
packages/runtime/src/type/config.ts | The code changes introduce a new RemoteInfoCommon interface that defines the common properties for remote information, including alias , shareScope , and type . This change likely aims to standardize the representation of remote information across the codebase, potentially to support more flexible and extensible module federation capabilities. |
packages/runtime/src/type/plugin.ts | The code changes introduce a new plugin system for the module-deferation bridge, allowing for the support of lifecycle hooks. This enables the bridge to handle more complex scenarios by providing a way to extend its functionality through plugins that can tap into various lifecycle events. |
packages/runtime/src/utils/plugin.ts | The changes introduce a new bridgeHook property to the Module['host'] interface, allowing for the registration of lifecycle hooks in the module-deferation bridge. This enhancement enables better support for various scenes that utilize the bridge capability. |
packages/runtime/src/utils/tool.ts | The code changes introduce a new function called processModuleAlias that takes a module name and a sub-path, and returns a processed module name. The function handles cases where the module name ends with a slash or the sub-path starts with a dot, and combines the module name and sub-path to create a new module name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 23
Configuration
Squadron Mode: essential
Commits Reviewed
44ac346ef4212a17e4b2d611ba0e7948ba804947...4e319bb2d0708da2b1f89bad9f1b2aec4c1029c2
Files Reviewed
- packages/bridge/bridge-react/src/create.tsx
- packages/bridge/bridge-react/src/lifecycle.ts
- packages/bridge/bridge-react/src/provider.tsx
- packages/bridge/bridge-react/src/remote/index.tsx
- packages/bridge/bridge-react/src/router-v6.tsx
- packages/bridge/bridge-react/src/router.tsx
- packages/bridge/vue3-bridge/src/create.ts
- packages/bridge/vue3-bridge/src/lifecycle.ts
- packages/bridge/vue3-bridge/src/provider.ts
- packages/bridge/vue3-bridge/src/remoteApp.tsx
- packages/runtime/src/helpers.ts
- packages/runtime/src/module/index.ts
- packages/runtime/src/plugins/snapshot/SnapshotHandler.ts
- packages/runtime/src/type/config.ts
- packages/runtime/src/type/plugin.ts
- packages/runtime/src/utils/plugin.ts
- packages/runtime/src/utils/tool.ts
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 31
Configuration
Squadron Mode: essential
Commits Reviewed
8712967dd8594e99bb012c3ef5520d2e84ee3b58...cd405919b9dd79637fb73bd57e07d359739d7219
Files Reviewed
- packages/runtime/src/module/index.ts
- packages/runtime/src/plugins/snapshot/SnapshotHandler.ts
- packages/bridge/bridge-react/src/provider.tsx
- packages/bridge/vue3-bridge/src/provider.ts
- packages/bridge/bridge-react/src/create.tsx
- packages/bridge/bridge-react/src/remote/index.tsx
- packages/bridge/vue3-bridge/src/create.ts
- packages/bridge/vue3-bridge/src/remoteApp.tsx
- packages/runtime/src/utils/plugin.ts
- packages/runtime/src/utils/tool.ts
- packages/runtime/src/type/config.ts
- packages/bridge/bridge-react/src/router.tsx
- packages/runtime/src/core.ts
- packages/runtime/src/embedded.ts
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
// keep symbol for module name always one format | ||
const symbolName = processModuleAlias(this.remoteInfo.name, expose); | ||
const wrapModuleFactory = this.wraperFactory(moduleFactory, symbolName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The symbolName generation and module factory wrapping could benefit from error handling to prevent potential runtime issues. Consider adding validation:
// keep symbol for module name always one format | |
const symbolName = processModuleAlias(this.remoteInfo.name, expose); | |
const wrapModuleFactory = this.wraperFactory(moduleFactory, symbolName); | |
// keep symbol for module name always one format | |
const symbolName = processModuleAlias(this.remoteInfo.name, expose); | |
assert(symbolName, `Failed to process module alias for ${expose}`); | |
const wrapModuleFactory = this.wraperFactory(moduleFactory, symbolName); | |
assert(wrapModuleFactory, `Failed to wrap module factory for ${symbolName}`); |
if (!loadFactory) { | ||
return wrapModuleFactory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The early return logic could be more explicit about what's being returned. Add a type annotation to improve code clarity:
if (!loadFactory) { | |
return wrapModuleFactory; | |
if (!loadFactory) { | |
return wrapModuleFactory as () => Promise<any>; | |
} |
remoteSnapshot: ModuleInfo; | ||
from: 'global' | 'manifest'; | ||
}>('loadRemoteSnapshot'), | ||
afterLoadSnapshot: new AsyncWaterfallHook<{ | ||
options: Options; | ||
moduleInfo: Remote; | ||
remoteSnapshot: ModuleInfo; | ||
}>('afterLoadSnapshot'), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hook definitions could benefit from more specific typing. Consider using a discriminated union type for the 'from' parameter to make the code more type-safe and self-documenting:
remoteSnapshot: ModuleInfo; | |
from: 'global' | 'manifest'; | |
}>('loadRemoteSnapshot'), | |
afterLoadSnapshot: new AsyncWaterfallHook<{ | |
options: Options; | |
moduleInfo: Remote; | |
remoteSnapshot: ModuleInfo; | |
}>('afterLoadSnapshot'), | |
}); | |
type SnapshotSource = { | |
type: 'global'; | |
} | { | |
type: 'manifest'; | |
manifestUrl: string; | |
}; | |
// Then use in hook: | |
loadRemoteSnapshot: new AsyncWaterfallHook<{ | |
options: Options; | |
moduleInfo: Remote; | |
remoteSnapshot: ModuleInfo; | |
from: SnapshotSource; | |
}>('loadRemoteSnapshot'), |
let mSnapshot; | ||
let gSnapshot; | ||
// global snapshot includes manifest or module info includes manifest | ||
if (globalRemoteSnapshot) { | ||
if (isManifestProvider(globalRemoteSnapshot)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable names 'mSnapshot' and 'gSnapshot' are not descriptive enough. Consider using more meaningful names to improve code readability:
let mSnapshot; | |
let gSnapshot; | |
// global snapshot includes manifest or module info includes manifest | |
if (globalRemoteSnapshot) { | |
if (isManifestProvider(globalRemoteSnapshot)) { | |
let moduleSnapshot; | |
let globalSnapshot; | |
// global snapshot includes manifest or module info includes manifest | |
if (globalRemoteSnapshot) { | |
if (isManifestProvider(gl |
await this.hooks.lifecycle.afterLoadSnapshot.emit({ | ||
options, | ||
moduleInfo, | ||
remoteSnapshot: mSnapshot, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The afterLoadSnapshot hook could benefit from error handling to ensure the system remains in a consistent state even if the hook handlers fail. Consider wrapping the hook emission in a try-catch block:
await this.hooks.lifecycle.afterLoadSnapshot.emit({ | |
options, | |
moduleInfo, | |
remoteSnapshot: mSnapshot, | |
}); | |
try { | |
await this.hooks.lifecycle.afterLoadSnapshot.emit({ | |
options, | |
moduleInfo, | |
remoteSnapshot: mSnapshot, | |
}); | |
} catch (error) { | |
console.error('Failed to process afterLoadSnapshot hook:', error); | |
// Consider whether to re-throw or handle the error | |
} |
packages/runtime/src/core.ts
Outdated
beforeBridgeRender: new SyncHook<[Record<string, any>], any>(), | ||
afterBridgeRender: new SyncHook<[Record<string, any>], any>(), | ||
beforeBridgeDestroy: new SyncHook<[Record<string, any>], any>(), | ||
afterBridgeDestroy: new SyncHook<[Record<string, any>], any>(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bridge hook lifecycle methods use a generic Record<string, any> type which is too permissive. Consider creating specific interfaces for each hook's payload to ensure type safety and better documentation. For example:
beforeBridgeRender: new SyncHook<[Record<string, any>], any>(), | |
afterBridgeRender: new SyncHook<[Record<string, any>], any>(), | |
beforeBridgeDestroy: new SyncHook<[Record<string, any>], any>(), | |
afterBridgeDestroy: new SyncHook<[Record<string, any>], any>(), | |
beforeBridgeRender: new SyncHook<[BridgeRenderContext], any>(), | |
afterBridgeRender: new SyncHook<[BridgeRenderResult], any>(), | |
beforeBridgeDestroy: new SyncHook<[BridgeDestroyContext], any>(), | |
afterBridgeDestroy: new SyncHook<[BridgeDestroyResult], any>(), |
packages/runtime/src/core.ts
Outdated
beforeBridgeRender: new SyncHook<[Record<string, any>], any>(), | ||
afterBridgeRender: new SyncHook<[Record<string, any>], any>(), | ||
beforeBridgeDestroy: new SyncHook<[Record<string, any>], any>(), | ||
afterBridgeDestroy: new SyncHook<[Record<string, any>], any>(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return type 'any' in the SyncHook generic parameters is too loose and could lead to type-safety issues. Consider defining specific return types for each hook to make the API more predictable and maintainable.
For the second code block (lines 291-297):
this.sharedHandler.hooks, | ||
this.snapshotHandler.hooks, | ||
this.loaderHook, | ||
this.bridgeHook, | ||
]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The registerPlugins call is passing hooks as an array which makes the relationship between plugins and hooks implicit. Consider restructuring to use a more explicit mapping of plugins to their corresponding hooks, making the code more maintainable and easier to understand. For example:
this.sharedHandler.hooks, | |
this.snapshotHandler.hooks, | |
this.loaderHook, | |
this.bridgeHook, | |
]); | |
this.registerPlugins({ | |
shared: this.sharedHandler.hooks, | |
snapshot: this.snapshotHandler.hooks, | |
loader: this.loaderHook, | |
bridge: this.bridgeHook, | |
}); |
initOptions(...args: Parameters<IndexModule.FederationHost['initOptions']>) { | ||
return this._getInstance().initOptions(...args); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The initOptions
method could benefit from type safety by explicitly declaring its return type. Based on the pattern seen in other methods, suggest adding the return type:
initOptions(...args: Parameters<IndexModule.FederationHost['initOptions']>) { | |
return this._getInstance().initOptions(...args); | |
} | |
initOptions(...args: Parameters<IndexModule.FederationHost['initOptions']>): ReturnType<IndexModule.FederationHost['initOptions']> { | |
return this._getInstance().initOptions(...args); | |
} |
get bridgeHook() { | ||
return this._getInstance().bridgeHook; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bridgeHook
getter lacks documentation explaining its purpose and usage. Since this appears to be part of a public API for lifecycle hooks, adding JSDoc would improve maintainability:
get bridgeHook() { | |
return this._getInstance().bridgeHook; | |
} | |
/** | |
* Gets the bridge hook instance that handles module federation bridge lifecycle events | |
* @returns The bridge hook instance | |
*/ | |
get bridgeHook() { | |
return this._getInstance().bridgeHook; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 4
Configuration
Squadron Mode: essential
Commits Reviewed
cd405919b9dd79637fb73bd57e07d359739d7219...8ff7ef654a77f4388ccb8e29dd95df9d3a447925
Files Reviewed
- packages/bridge/bridge-react/src/provider.tsx
- packages/runtime/src/core.ts
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
bridgeHook = new PluginSystem({ | ||
beforeBridgeRender: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
afterBridgeRender: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
beforeBridgeDestroy: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
afterBridgeDestroy: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The bridgeHook initialization could benefit from a dedicated interface to improve code organization and reusability. Extract the hook definitions into a separate interface:
bridgeHook = new PluginSystem({ | |
beforeBridgeRender: new SyncHook< | |
[Record<string, any>], | |
void | Record<string, any> | |
>(), | |
afterBridgeRender: new SyncHook< | |
[Record<string, any>], | |
void | Record<string, any> | |
>(), | |
beforeBridgeDestroy: new SyncHook< | |
[Record<string, any>], | |
void | Record<string, any> | |
>(), | |
afterBridgeDestroy: new SyncHook< | |
[Record<string, any>], | |
void | Record<string, any> | |
>(), | |
}); | |
interface BridgeHooks { | |
beforeBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>; | |
afterBridgeRender: SyncHook<[Record<string, any>], void | Record<string, any>>; | |
beforeBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>; | |
afterBridgeDestroy: SyncHook<[Record<string, any>], void | Record<string, any>>; | |
} | |
bridgeHook = new PluginSystem<BridgeHooks>({ | |
beforeBridgeRender: new SyncHook(), | |
afterBridgeRender: new SyncHook(), | |
beforeBridgeDestroy: new SyncHook(), | |
afterBridgeDestroy: new SyncHook(), | |
}); |
beforeBridgeRender: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
afterBridgeRender: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
beforeBridgeDestroy: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), | ||
afterBridgeDestroy: new SyncHook< | ||
[Record<string, any>], | ||
void | Record<string, any> | ||
>(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return types for the hooks (void | Record<string, any>) are inconsistent with typical lifecycle patterns. Consider standardizing the return types - lifecycle hooks typically either return void (for side effects) or a specific result type. If modification of the context is needed, it should be done through the context parameter rather than the return value.
@@ -126,6 +126,24 @@ export class FederationHost { | |||
Promise<(() => Promise<Module>) | undefined> | |||
>(), | |||
}); | |||
bridgeHook = new PluginSystem({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The variable name bridgeHook
could be more descriptive. Consider renaming to bridgeLifecycle
or bridgePluginSystem
to better reflect its purpose and functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 1
Configuration
Squadron Mode: essential
Commits Reviewed
8ff7ef654a77f4388ccb8e29dd95df9d3a447925...dfb6d7761330c4fa21e067e8b770d57bc5da9a3f
Files Reviewed
- packages/bridge/vue3-bridge/src/provider.ts
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
beforeBridgeRender?: (params: RenderFnParams) => void | Record<string, any>; | ||
afterBridgeRender?: (params: RenderFnParams) => void | Record<string, any>; | ||
beforeBridgeDestroy?: (params: DestroyParams) => void | Record<string, any>; | ||
afterBridgeDestroy?: (params: DestroyParams) => void | Record<string, any>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hook types should be more consistent in their return types. Currently, all hooks allow returning Record<string, any>
, but typically only beforeBridgeRender needs to return extra props. Consider:
beforeBridgeRender?: (params: RenderFnParams) => void | Record<string, any>; | |
afterBridgeRender?: (params: RenderFnParams) => void | Record<string, any>; | |
beforeBridgeDestroy?: (params: DestroyParams) => void | Record<string, any>; | |
afterBridgeDestroy?: (params: DestroyParams) => void | Record<string, any>; | |
beforeBridgeRender?: (params: RenderFnParams) => void | { extraProps?: Record<string, any> }; | |
afterBridgeRender?: (params: RenderFnParams) => void; | |
beforeBridgeDestroy?: (params: DestroyParams) => void; | |
afterBridgeDestroy?: (params: DestroyParams) => void; |
This makes the API more explicit about which hooks can meaningfully return data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 2
Configuration
Squadron Mode: essential
Commits Reviewed
dfb6d7761330c4fa21e067e8b770d57bc5da9a3f...f2e962492ecaab4795c702beaa18acabeeabd49a
Files Reviewed
- packages/runtime/src/type/plugin.ts
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
type ModuleBridgeLifeCycle = Module['host']['bridgeHook']['lifecycle']; | ||
type ModuleBridgeLifeCycleCyclePartial = Partial<{ | ||
[k in keyof ModuleBridgeLifeCycle]: Parameters< | ||
ModuleBridgeLifeCycle[k]['on'] | ||
>[0]; | ||
}>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type definition for ModuleBridgeLifeCycle
and ModuleBridgeLifeCycleCyclePartial
could be simplified using a helper type to reduce code duplication. Here's a suggested improvement:
type ModuleBridgeLifeCycle = Module['host']['bridgeHook']['lifecycle']; | |
type ModuleBridgeLifeCycleCyclePartial = Partial<{ | |
[k in keyof ModuleBridgeLifeCycle]: Parameters< | |
ModuleBridgeLifeCycle[k]['on'] | |
>[0]; | |
}>; | |
type CreateLifeCyclePartial<T> = Partial<{ | |
[K in keyof T]: Parameters<T[K]['on']>[0]; | |
}>; | |
type ModuleBridgeLifeCycle = Module['host']['bridgeHook']['lifecycle']; | |
type ModuleBridgeLifeCycleCyclePartial = CreateLifeCyclePartial<ModuleBridgeLifeCycle>; |
This pattern could be reused for other similar lifecycle type definitions, making the code more maintainable and reducing repetition.
SnapshotLifeCycleCyclePartial & | ||
SharedLifeCycleCyclePartial & | ||
RemoteLifeCycleCyclePartial & | ||
ModuleLifeCycleCyclePartial & { | ||
ModuleLifeCycleCyclePartial & | ||
ModuleBridgeLifeCycleCyclePartial & { | ||
name: string; | ||
version?: string; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The plugin interface combines multiple lifecycle partials. Consider adding a descriptive type comment to explain the purpose of each lifecycle component and their relationships. Additionally, the optional version field could benefit from a more specific type if there are expected version formats:
SnapshotLifeCycleCyclePartial & | |
SharedLifeCycleCyclePartial & | |
RemoteLifeCycleCyclePartial & | |
ModuleLifeCycleCyclePartial & { | |
ModuleLifeCycleCyclePartial & | |
ModuleBridgeLifeCycleCyclePartial & { | |
name: string; | |
version?: string; | |
}; | |
/** | |
* Plugin configuration interface combining multiple lifecycle hooks: | |
* - SnapshotLifeCycle: Handles snapshot-related events | |
* - SharedLifeCycle: Manages shared module events | |
* - RemoteLifeCycle: Controls remote module loading | |
* - ModuleLifeCycle: Core module lifecycle events | |
* - ModuleBridgeLifeCycle: Bridge-specific events | |
*/ | |
type Plugin = | |
SnapshotLifeCycleCyclePartial & | |
SharedLifeCycleCyclePartial & | |
RemoteLifeCycleCyclePartial & | |
ModuleLifeCycleCyclePartial & | |
ModuleBridgeLifeCycleCyclePartial & { | |
name: string; | |
version?: `${number}.${number}.${number}`; // Semantic versioning format | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incremental Review
Comments posted: 2
Configuration
Squadron Mode: essential
Commits Reviewed
f2e962492ecaab4795c702beaa18acabeeabd49a...b25a91bd26bc94906c08848d36111af48e2a009d
Files Reviewed
- packages/bridge/bridge-react/src/provider.tsx
- packages/bridge/bridge-react/src/remote/index.tsx
Files Ignored
These files were ignored due to the filter in the squadron.yaml file.
- .changeset/great-feet-rule.md
- packages/bridge/bridge-react/package.json
- packages/bridge/vue3-bridge/package.json
- pnpm-lock.yaml
type RenderParams = RenderFnParams & any; | ||
type DestroyParams = { | ||
moduleName: string; | ||
dom: HTMLElement; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type definitions could be improved for better type safety and consistency:
RenderParams
using& any
defeats TypeScript's type checking. Define explicit parameters instead.DestroyParams
should align with the suggestedBaseBridgeParams
pattern.
Here's a suggested improvement:
type RenderParams = RenderFnParams & any; | |
type DestroyParams = { | |
moduleName: string; | |
dom: HTMLElement; | |
}; | |
type RenderParams = RenderFnParams & { | |
// Add specific render parameters here | |
}; | |
type DestroyParams = BaseBridgeParams & { | |
moduleName: string; | |
}; |
This maintains type safety while providing a consistent parameter structure across the bridge lifecycle hooks.
providerInfoRef.current?.destroy({ | ||
moduleName, | ||
dom: renderDom.current, | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The destroy call should handle errors gracefully to prevent potential crashes during cleanup. Consider wrapping it in a try-catch block:
providerInfoRef.current?.destroy({ | |
moduleName, | |
dom: renderDom.current, | |
}); | |
} | |
try { | |
providerInfoRef.current?.destroy({ | |
moduleName, | |
dom: renderDom.current, | |
}); | |
} catch (error) { | |
console.error('Error during bridge component destruction:', error); | |
} |
This ensures that any errors during cleanup won't propagate up and potentially break the application's unmounting process.
Description
feat: support lifecycyle hooks in module-deferation bridge so that we can support more scene with bridge capability
Related Issue
Types of changes
Checklist