#
registerRemoteModules
Register one or many remote module(s). During the registration process, the module register function will be invoked with a FireflyRuntime instance and an optional context object. To defer the registration of specific routes or navigation items, a registration function can return an anonymous function.
A remote module is a module that is not part of the current build but is loaded at runtime from a remote server.
#
Reference
registerRemoteModules(remotes: [], runtime, options?: { context? })
#
Parameters
remotes: An array ofRemoteDefinition(view theRemote definition section).runtime: AFireflyRuntimeinstance.options: An optional object literal of options:context: An optional context object that will be pass to the registration function.
#
Returns
A Promise object with an array of RemoteModuleRegistrationError if any error happens during the registration.
RemoteModuleRegistrationError:remoteName: The name of the remote module that failed to load.moduleName: The name of themodule that Squide attempted to recover.error: The original error object.
#
Usage
#
Register a remote module
import { FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly";
const runtime = new FireflyRuntime();
const Remotes: RemoteDefinition = [
{ name: "remote1" }
];
await registerRemoteModules(Remotes, runtime);
import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly";
import { AboutPage } from "./AboutPage.tsx";
export const register: ModuleRegisterFunction<FireflyRuntime> = async runtime => {
runtime.registerRoute({
path: "/about",
element: <AboutPage />
});
runtime.registerNavigationItem({
$label: "About",
to: "/about"
});
}
#
Defer the registration of routes or navigation items
Sometimes, data must be fetched to determine which routes or navigation items should be registered by a given module. To address this, Squide offers a two-phase registration mechanism:
The first phase allows modules to register their routes and navigation items that are not dependent on initial data (in addition to their MSW request handlers when fake endpoints are available).
The second phase enables modules to register routes and navigation items that are dependent on initial data. Such a use case would be determining whether a route should be registered based on a feature flag. We refer to this second phase as deferred registrations.
To defer a registration to the second phase, a module registration function can return an anonymous function. Once the modules are registered and the completeRemoteModuleRegistrations function is called, the deferred registration functions will be executed.
import { FireflyRuntime, completeRemoteModuleRegistrations, registerRemoteModules, type RemoteDefinition } from "@squide/firefly";
import { fetchFeatureFlags } from "@sample/shared";
const runtime = new FireflyRuntime();
const Remotes: RemoteDefinition = [
{ name: "remote1" }
];
await registerRemoteModules(Remotes, runtime);
// Don't fetch data in the bootstrapping code for a real application. This is done here
// strictly for demonstration purpose.
const featureFlags = await fetchFeatureFlags();
// Complete the module registrations with the feature flags data.
await completeRemoteModuleRegistrations(runtime, { featureFlags });
import type { ModuleRegisterFunction, FireflyRuntime } from "@squide/firefly";
import type { DeferredRegistrationData } from "@sample/shared";
import { AboutPage } from "./AboutPage.tsx";
import { FeatureAPage } from "./FeatureAPage.tsx";
export const register: ModuleRegisterFunction<FireflyRuntime, unknown, DeferredRegistrationData> = async runtime => {
runtime.registerRoute({
path: "/about",
element: <AboutPage />
});
runtime.registerNavigationItem({
$label: "About",
to: "/about"
});
// Once the feature flags has been loaded by the host application, by completing the module registrations process,
// the deferred registration function will be called with the feature flags data.
return ({ featureFlags } = {}) => {
// Only register the "feature-a" route and navigation item if the feature is active.
if (featureFlags.featureA) {
runtime.registerRoute({
path: "/feature-a",
element: <FeatureAPage />
});
runtime.registerNavigationItem({
$label: "Feature A",
to: "/feature-a"
});
}
};
}
#
Handle the registration errors
import { FireflyRuntime, registerRemoteModules, type RemoteDefinition } from "@squide/firefly";
const runtime = new FireflyRuntime();
const Remotes: RemoteDefinition = [
{ name: "remote1" }
];
(await registerRemoteModules(Remotes, runtime)).forEach(x => {
console.log(x);
});
#
Remote definition
To ease the configuration of remote modules, make sure that you first import the RemoteDefinition type and assign it to your remote definitions array declaration.
import type { RemoteDefinition } from "@squide/firefly";
const Remotes: RemoteDefinition = [
{ name: "remote1" }
];
#
name
The name property of a remote definition must match the name property defined in the remote module ModuleFederationPlugin configuration.
If you are relying on either the Squide defineDevRemoteModuleConfig or defineBuildRemoteModuleConfig functions to add the ModuleFederationPlugin to the remote module webpack configuration object, then the remote module name is the second argument of the function.
In the following exemple, the remote module name is remote1.
const Remotes: RemoteDefinition = [
{ name: "remote1" }
];
// @ts-check
import { defineDevRemoteModuleConfig } from "@squide/firefly-webpack-configs";
import { swcConfig } from "./swc.dev.js";
export default defineDevRemoteModuleConfig(swcConfig, "remote1", 8081);