Skip to content
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: support lifecycyle hooks in module-deferation bridge #2992

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

danpeen
Copy link
Contributor

@danpeen danpeen commented Sep 24, 2024

Description

feat: support lifecycyle hooks in module-deferation bridge so that we can support more scene with bridge capability

Related Issue

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have updated the documentation.

Copy link

changeset-bot bot commented Sep 24, 2024

🦋 Changeset detected

Latest commit: 8588609

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 39 packages
Name Type
@module-federation/bridge-react Patch
@module-federation/bridge-vue3 Patch
@module-federation/runtime Patch
host Patch
host-v5 Patch
remote1 Patch
remote2 Patch
remote4 Patch
host-vue3 Patch
remote3 Patch
@module-federation/devtools Patch
@module-federation/data-prefetch Patch
@module-federation/dts-plugin Patch
@module-federation/nextjs-mf Patch
@module-federation/node Patch
@module-federation/retry-plugin Patch
@module-federation/runtime-tools Patch
@module-federation/webpack-bundler-runtime Patch
@module-federation/enhanced Patch
@module-federation/modern-js Patch
@module-federation/rspack Patch
@module-federation/rsbuild-plugin Patch
3008-runtime-remote Patch
@module-federation/modernjs Patch
modernjs-ssr-dynamic-nested-remote Patch
modernjs-ssr-dynamic-remote-new-version Patch
modernjs-ssr-dynamic-remote Patch
modernjs-ssr-host Patch
modernjs-ssr-nested-remote Patch
modernjs-ssr-remote-new-version Patch
modernjs-ssr-remote Patch
@module-federation/sdk Patch
@module-federation/managers Patch
@module-federation/manifest Patch
@module-federation/third-party-dts-extractor Patch
@module-federation/bridge-shared Patch
@module-federation/bridge-react-webpack-plugin Patch
@module-federation/esbuild Patch
@module-federation/utilities Patch

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

Copy link

netlify bot commented Sep 24, 2024

Deploy Preview for module-federation-docs ready!

Name Link
🔨 Latest commit 8588609
🔍 Latest deploy log https://app.netlify.com/sites/module-federation-docs/deploys/6711d93546c15700087a9c6b
😎 Deploy Preview https://deploy-preview-2992--module-federation-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link
Contributor

@squadronai squadronai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

This pull request introduces support for lifecycle hooks in the module-deferation bridge, allowing for more scene-based capabilities with the bridge. The changes span across multiple files and packages, including the addition of new lifecycle hooks, utility functions, and type definitions.

The key changes include:

  • Addition of beforeBridgeRender, afterBridgeRender, beforeBridgeDestroy, and afterBridgeDestroy hooks in the bridge-react and vue3-bridge packages, enabling better control and integration with various scenes that utilize the bridge capability.
  • Improvements to the SnapshotHandler class in the runtime package, introducing a new afterLoadSnapshot hook to support additional processing or cleanup after a remote snapshot is loaded.
  • Enhancements to the PluginSystem in the runtime package, allowing for the registration of plugins with lifecycle hooks.
  • Utility functions and type definitions to ensure consistent module name formatting and support for the new lifecycle hooks.

These changes aim to provide more flexibility and control over the rendering and destruction of the bridge component, enabling better integration with diverse scenes that utilize the bridge capability.

File Summaries
File Summary
packages/bridge/bridge-react/src/create.tsx The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene-based capabilities with the bridge. The changes include the addition of an ErrorBoundary component and the integration of the ProviderParams type from the @module-federation/bridge-shared package.
packages/bridge/bridge-react/src/lifecycle.ts The code changes introduce a new feature to support lifecycle hooks in the module-deferation bridge. This allows for more flexibility and control over the rendering and destruction of the bridge component, enabling better integration with various scenes that utilize the bridge capability.
packages/bridge/bridge-react/src/provider.tsx The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more flexibility in handling different scenarios with bridge capabilities. The changes include the addition of beforeBridgeRender, afterBridgeRender, beforeBridgeDestroy, and afterBridgeDestroy hooks, which can be used to perform custom actions before and after the bridge rendering and destruction processes. These hooks can be used to pass additional props or perform cleanup tasks as needed.
packages/bridge/bridge-react/src/remote/index.tsx The code changes introduce support for lifecycle hooks in the module-federation bridge, allowing for more flexibility in handling different scenarios with the bridge capability. The changes include the addition of beforeBridgeRender and afterBridgeDestroy hooks, which can be used to perform custom actions before and after the remote component is rendered and destroyed, respectively. Additionally, the code includes utility functions to extract the module name and generate a default class name for the root DOM element of the remote component.
packages/bridge/bridge-react/src/router-v5.tsx The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene capabilities with the bridge. The changes include the removal of an unnecessary import statement and the addition of new functionality to the RouterContext component.
packages/bridge/bridge-react/src/router.tsx The changes in this file introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene-specific functionality to be supported by the bridge capability. The key modification is the addition of a new parameter, basename, to the createBrowserRouter function, which can now be retrieved from the routerContextProps object or the router object.
packages/bridge/vue3-bridge/src/create.ts The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene-specific capabilities to be supported. The key modifications include adding the useRoute function from vue-router and updating the imports to accommodate the new feature.
packages/bridge/vue3-bridge/src/lifecycle.ts The code changes introduce a new feature to support lifecycle hooks in the module-deferation bridge. This allows for more flexibility and support for different scenes with bridge capability. The changes include the implementation of a plugin system with two new hooks: beforeBridgeRender and beforeBridgeDestroy, which can be used to extend the functionality of the bridge.
packages/bridge/vue3-bridge/src/provider.ts The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene support with bridge capability. The changes include adding a renderLifecycle function that is called during the creation of the bridge component, and a destroyLifecycle function that is called during the destruction of the bridge component.
packages/bridge/vue3-bridge/src/remoteApp.tsx The code changes introduce support for lifecycle hooks in the module-federation bridge, allowing for better handling of different scenes with bridge capabilities. The key modifications include adding a registerBridgeLifeCycle function, which emits beforeBridgeRender and beforeBridgeDestroy events, providing hooks for managing the lifecycle of the remote component. These changes enhance the flexibility and extensibility of the module-federation bridge.
packages/runtime/src/helpers.ts The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene-specific functionality to be supported by the bridge. The changes include the addition of new utility functions and properties to the GlobalUtils object, which provide access to plugin registration and lifecycle hook handling capabilities.
packages/runtime/src/module/index.ts The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for better handling of various scenes with bridge capability. The key modifications include adding a new utility function processModuleAlias to ensure consistent module name formatting, and updating the wrapModuleFactory 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 is loaded. The purpose of this hook is to provide a way for other parts of the application to perform additional processing or cleanup after a snapshot is loaded, potentially supporting more scenarios with the bridge capability.
packages/runtime/src/type/config.ts The code changes introduce a new interface called RemoteInfoCommon that defines the common properties for remote information, including alias, shareScope, and type. This change aims to support lifecycle hooks in the module-deferation bridge, enabling the system to handle more diverse scenarios with bridge capabilities.
packages/runtime/src/type/plugin.ts The code changes introduce a new type LifeCycle that combines several partial types, including CoreLifeCyclePartial, SnapshotLifeCycleCyclePartial, SharedLifeCycleCyclePartial, RemoteLifeCycleCyclePartial, and ModuleLifeCycleCyclePartial. The purpose of this change is to create a more comprehensive type definition for the FederationRuntimePlugin type, which now includes the LifeCycle type as a generic parameter.
packages/runtime/src/utils/plugin.ts The code changes introduce support for lifecycle hooks in the module-deferation bridge, allowing for more scene-specific capabilities to be supported. The changes include the addition of a PluginSystem type parameter to the registerPlugins function, enabling the registration of plugins with lifecycle hooks.
packages/runtime/src/utils/tool.ts The code changes introduce a new utility 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 and the sub-path starts with a dot, ensuring the final module name is correctly formatted.

Copy link
Contributor

@squadronai squadronai bot left a 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

@module-federation module-federation deleted a comment from squadronai bot Sep 26, 2024
@module-federation module-federation deleted a comment from squadronai bot Sep 26, 2024
@module-federation module-federation deleted a comment from squadronai bot Sep 26, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 8, 2024
Copy link
Contributor

@squadronai squadronai bot left a 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

4e319bb2d0708da2b1f89bad9f1b2aec4c1029c2...a6c9c9748544a6e4cadf6d7df788b39c6eab74ed

Files Reviewed
  • packages/bridge/bridge-react/src/provider.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

@module-federation module-federation deleted a comment from squadronai bot Oct 11, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 11, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 11, 2024
@module-federation module-federation deleted a comment from squadronai bot Oct 11, 2024
Copy link
Contributor

@squadronai squadronai bot left a 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: 3

Configuration

Squadron Mode: essential

Commits Reviewed

a6c9c9748544a6e4cadf6d7df788b39c6eab74ed...10bc78b7075241c61b95e20783021e7e962ecfcb

Files Reviewed
  • packages/bridge/bridge-react/src/provider.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

Comment on lines +63 to +65
const beforeBridgeRender =
(bridgeInfo?.hooks && bridgeInfo?.hooks.beforeBridgeRender) ||
params?.hooks?.beforeBridgeRender;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code for retrieving beforeBridgeRender can be simplified using the nullish coalescing operator:

Suggested change
const beforeBridgeRender =
(bridgeInfo?.hooks && bridgeInfo?.hooks.beforeBridgeRender) ||
params?.hooks?.beforeBridgeRender;
const beforeBridgeRender = bridgeInfo?.hooks?.beforeBridgeRender ?? params?.hooks?.beforeBridgeRender;

This change improves readability and reduces the chance of errors.

Comment on lines 68 to 75
const beforeBridgeRenderRes =
beforeBridgeRender && beforeBridgeRender(info);
const componentProps =
beforeBridgeRenderRes &&
typeof beforeBridgeRenderRes === 'object' &&
beforeBridgeRenderRes?.extraProps
? beforeBridgeRenderRes?.extraProps
: {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for handling beforeBridgeRenderRes can be simplified using optional chaining and nullish coalescing:

Suggested change
const beforeBridgeRenderRes =
beforeBridgeRender && beforeBridgeRender(info);
const componentProps =
beforeBridgeRenderRes &&
typeof beforeBridgeRenderRes === 'object' &&
beforeBridgeRenderRes?.extraProps
? beforeBridgeRenderRes?.extraProps
: {};
const beforeBridgeRenderRes = beforeBridgeRender?.(info);
const componentProps = beforeBridgeRenderRes?.extraProps ?? {};

This change reduces complexity and improves readability while maintaining the same functionality.

@@ -56,11 +83,12 @@ export function createBridgeComponent<T>(bridgeInfo: ProviderFnParams<T>) {
basename,
memoryRoute,
}}
propsInfo={propsInfo}
// propsInfo={propsInfo}
propsInfo={{ propsInfo, ...componentProps } as T}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spread operator is being used to merge propsInfo with componentProps, which might lead to unintended overwriting of properties. Consider using a more explicit merging strategy:

Suggested change
propsInfo={{ propsInfo, ...componentProps } as T}
propsInfo={{ ...propsInfo, ...componentProps } as T}

This ensures that componentProps takes precedence over propsInfo if there are any conflicting keys.

Copy link
Contributor

@squadronai squadronai bot left a 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

10bc78b7075241c61b95e20783021e7e962ecfcb...19acf8b1715499a931e064089a796410d967498c

Files Reviewed
  • packages/bridge/bridge-react/src/lifecycle.ts
  • 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

Comment on lines +5 to +15
const { registerPlugins, pluginHelper } = helper.global;
const host = getInstance();
const pluginSystem = new pluginHelper.PluginSystem({
beforeBridgeRender: new pluginHelper.SyncHook<[Record<string, any>], any>(),
afterBridgeRender: new pluginHelper.SyncHook<[Record<string, any>], any>(),
beforeBridgeDestroy: new pluginHelper.SyncHook<
[Record<string, any>],
any
>(),
afterBridgeDestroy: new pluginHelper.SyncHook<[Record<string, any>], any>(),
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code introduces a plugin system with lifecycle hooks for a bridge component. While the implementation looks good, there are a few suggestions to improve type safety and readability:

  1. Consider using more specific types for the hook parameters instead of Record<string, any>. This will provide better type checking and documentation.

  2. The SyncHook generic type could be simplified if all hooks have the same signature. You could define a type alias for the hook signature.

Here's an example of how you could improve the code:

Suggested change
const { registerPlugins, pluginHelper } = helper.global;
const host = getInstance();
const pluginSystem = new pluginHelper.PluginSystem({
beforeBridgeRender: new pluginHelper.SyncHook<[Record<string, any>], any>(),
afterBridgeRender: new pluginHelper.SyncHook<[Record<string, any>], any>(),
beforeBridgeDestroy: new pluginHelper.SyncHook<
[Record<string, any>],
any
>(),
afterBridgeDestroy: new pluginHelper.SyncHook<[Record<string, any>], any>(),
});
type BridgeHookParams = {
// Define specific properties here
bridgeProps: Record<string, unknown>;
// Add more relevant properties
};
type BridgeHook = pluginHelper.SyncHook<[BridgeHookParams], void>;
const pluginSystem = new pluginHelper.PluginSystem({
beforeBridgeRender: new BridgeHook(),
afterBridgeRender: new BridgeHook(),
beforeBridgeDestroy: new BridgeHook(),
afterBridgeDestroy: new BridgeHook(),
});

This change improves type safety and makes the code more concise and easier to maintain.

Comment on lines +84 to +100
if (bridgeHook && bridgeHook?.lifecycle?.beforeBridgeRender) {
const beforeBridgeRenderRes =
bridgeHook?.lifecycle?.beforeBridgeRender.emit({
...renderProps,
});
const extraProps =
beforeBridgeRenderRes &&
typeof beforeBridgeRenderRes === 'object' &&
beforeBridgeRenderRes?.extraProps
? beforeBridgeRenderRes?.extraProps
: {};

renderProps = {
...renderProps,
...extraProps,
} as any;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lifecycle hook implementation can be simplified and made more robust:

  1. Use optional chaining to simplify nested property access.
  2. Use destructuring to extract the beforeBridgeRender method.
  3. Use the nullish coalescing operator for default values.
  4. Simplify the type check for beforeBridgeRenderRes.

Here's a suggested refactoring:

Suggested change
if (bridgeHook && bridgeHook?.lifecycle?.beforeBridgeRender) {
const beforeBridgeRenderRes =
bridgeHook?.lifecycle?.beforeBridgeRender.emit({
...renderProps,
});
const extraProps =
beforeBridgeRenderRes &&
typeof beforeBridgeRenderRes === 'object' &&
beforeBridgeRenderRes?.extraProps
? beforeBridgeRenderRes?.extraProps
: {};
renderProps = {
...renderProps,
...extraProps,
} as any;
}
if (bridgeHook?.lifecycle?.beforeBridgeRender) {
const { beforeBridgeRender } = bridgeHook.lifecycle;
const beforeBridgeRenderRes = beforeBridgeRender.emit(renderProps);
const extraProps = beforeBridgeRenderRes?.extraProps ?? {};
renderProps = {
...renderProps,
...extraProps,
};
}

This change improves readability and reduces the chance of runtime errors.

renderProps = {
...renderProps,
...extraProps,
} as any;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the as any type assertion. Instead, properly type renderProps or use a more specific type assertion if necessary. Avoiding any helps maintain type safety throughout your codebase.

Suggested change
} as any;
} as RenderProps; // Replace 'RenderProps' with the actual type of renderProps

Comment on lines +112 to +116
if (bridgeHook && bridgeHook?.lifecycle?.afterBridgeDestroy) {
bridgeHook?.lifecycle?.afterBridgeDestroy.emit({
moduleName,
dom: renderDom.current,
basename,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the beforeBridgeRender hook, the afterBridgeDestroy hook implementation can be simplified:

Suggested change
if (bridgeHook && bridgeHook?.lifecycle?.afterBridgeDestroy) {
bridgeHook?.lifecycle?.afterBridgeDestroy.emit({
moduleName,
dom: renderDom.current,
basename,
if (bridgeHook?.lifecycle?.afterBridgeDestroy) {
bridgeHook.lifecycle.afterBridgeDestroy.emit({
moduleName,
dom: renderDom.current,
basename,

This change uses optional chaining to simplify the nested property access and improve readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants