SCION Microfrontend Platform is a TypeScript-based open-source library that helps to implement a microfrontend architecture using iframes.
MicrofrontendPlatformClient#signalReady
to void (2ebd65d)platform: dropping deprecated API and backward compatibility introduced a breaking change for host and client applications.
To migrate:
1.0.0-rc.13
or higher.ManifestService.lookupApplications$
has been removed; use ManifestService.applications
instead.Capability.requiredParams
has been removed; declare required parameters via Capability.params
instead and mark it as required.Capability.optionalParams
has been removed; declare optional parameters via Capability.params
instead and mark it as non-required.HttpClient
in client as only used in the host (e47ed8b)ManifestObject
from public API since internal (36f0dd8)platform: reducing the bundle size in client applications introduced a breaking change for host and client applications. The communication protocol between host and client has not changed, i.e., host and clients can be updated independently to the new version.
To enable tree-shaking of the SCION Microfrontend Platform, the platform was split into three separate entry points. This reduced the raw size of the library in a client application by more than 50%, from 120 KB to 40 KB.
Platform Entry Points:
MicrofrontendPlatformHost
to configure and start the platform in the host application;MicrofrontendPlatformClient
to connect to the platform from a microfrontend;MicrofrontendPlatform
to react to platform lifecycle events and stop the platform;To migrate the host application:
MicrofrontendPlatformHost.start
instead of MicrofrontendPlatform.startHost
MicrofrontendPlatformHost.startupProgress$
instead of MicrofrontendPlatform.startupProgress$
To migrate the client application:
MicrofrontendPlatformClient.connect
method instead of MicrofrontendPlatform.connectToHost
MicrofrontendPlatformClient.isConnected
method instead of MicrofrontendPlatform.isConnectedToHost
platform/client: removing client startup progress introduced a breaking change in the client.
To reduce the size of the client bundle, the API for monitoring the startup progress in the client has been removed. This API is useful in the host, but not in the client, because the client only connects to the host and does not perform any long-running operation. There is no replacement.
platform/host: removing ManifestObject
from public API introduced a breaking change.
The ManifestObject
interface is the internal representation of capabilities and intensions in the platform host. It was never intended to be public API.
To migrate:
Capability | Intention
.beforeunload
to avoid posting messages to disposed window (3969c17), closes #168
platform/host: Property for configuring a secondary origin has been renamed from messageOrigin
to secondaryOrigin
. This breaking change only refers to the host.
To migrate, configure the additional allowed origin via the secondaryOrigin
property instead of messageOrigin
, as following:
await MicrofrontendPlatform.startHost({
applications: [
{symbolicName: 'client', manifestUrl: 'https://app/manifest.json', secondaryOrigin: 'https://secondary'},
],
});
platform/host: The host now performs liveness probes to detect and remove stale clients, instead of relying on the heartbeats emitted by the clients of previous versions.
The breaking change only refers to the host. The communication protocol between host and client has NOT changed. You can independently update host and clients to the new version.
To migrate setting of a custom probe configuration in the host, specify the liveness
instead of heartbeatInterval
property, as follows:
MicrofrontendPlatform.startHost({
liveness: {interval: 60, timeout: 10},
// omitted rest of the config
});
platform: Optimization of mouse event dispatching introduced a breaking change for Angular applications.
IMPORTANT: For Angular applications, we strongly recommend replacing zone-specific decorators for MessageClient
and IntentClient
with an ObservableDecorator
. Otherwise, you may experience performance degradation due to frequent change detection cycles.
It turned out that Angular zone synchronization with decorators for MessageClient
and IntentClient
is not sufficient and that observables should emit in the same Angular zone in which the subscription was performed. Using the new ObservableDecorator
API, Angular zone synchronization can now be performed in a single place for all observables exposed by the SCION Microfrontend Platform.
To migrate:
MessageClient
and IntentClient
including their registration in the bean manager (e.g., NgZoneMessageClientDecorator
and NgZoneIntentClientDecorator
).NgZoneObservableDecorator
and register it in the bean manager before starting the platform. Note to register it as a bean, not as a decorator.For a complete example and detailed instructions, see https://scion-microfrontend-platform-developer-guide.vercel.app/#chapter:angular-integration-guide:synchronizing-rxjs-observables-with-angular-zone.
/**
* Mirrors the source, but ensures subscription and emission {@link NgZone} to be identical.
*/
export class NgZoneObservableDecorator implements ObservableDecorator {
constructor(private zone: NgZone) {
}
public decorate$<T>(source$: Observable<T>): Observable<T> {
return new Observable<T>(observer => {
const insideAngular = NgZone.isInAngularZone();
const subscription = source$
.pipe(
subscribeInside(fn => this.zone.runOutsideAngular(fn)),
observeInside(fn => insideAngular ? this.zone.run(fn) : this.zone.runOutsideAngular(fn)),
)
.subscribe(observer);
return () => subscription.unsubscribe();
});
}
}
const zone: NgZone = ...;
// Register decorator
Beans.register(ObservableDecorator, {useValue: new NgZoneObservableDecorator(zone)});
// Connect to the host from a micro app
zone.runOutsideAngular(() => MicrofrontendPlatform.connectToHost(...));
// Start platform host in host app
zone.runOutsideAngular(() => MicrofrontendPlatform.startHost(...));
platform: dropping support for wildcard capability qualifiers and optional wildcard intention qualifiers introduced a breaking change in the Intention API.
To migrate:
*
) wildcard capability qualifier entries with required params.?
) wildcard capability qualifier entries with optional params.QualifierMatcher
to match qualifiers, construct it without flags. The matcher now always evaluates asterisk wildcards in the pattern passed in the constructor.Capability in Manifest of App 1
{
"name": "App 1",
"capabilities": [
{
"type": "microfrontend",
"qualifier": {
"entity": "person",
"id": "*",
"readonly": "?"
},
"private": false,
"properties": {
"path": "person/:id?readonly=:readonly"
}
}
]
}
Intention in Manifest of App 2
{
"name": "App 2",
"intentions": [
{
"type": "microfrontend",
"qualifier": {
"entity": "person",
"id": "*",
"readonly": "?"
}
}
]
}
Sending Intent in App 2
const intent: Intent = {
type: 'microfrontend',
qualifier: {
entity: 'person',
id: '123',
readonly: true
}
};
Beans.get(IntentClient).publish(intent);
Capability in Manifest of App 1
{
"name": "App 1",
"capabilities": [
{
"type": "microfrontend",
"qualifier": {
"entity": "person"
},
"params": [
{
"name": "id",
"required": true
},
{
"name": "readonly",
"required": false
}
],
"private": false,
"properties": {
"path": "person/:id?readonly=:readonly"
}
}
]
}
Intention in Manifest of App 2
{
"name": "App 2",
"intentions": [
{
"type": "microfrontend",
"qualifier": {
"entity": "person"
}
}
]
}
Sending Intent in App 2
const intent: Intent = {
type: 'microfrontend',
qualifier: {
entity: 'person'
},
params: new Map().set('id', '123').set('readonly', true)
};
Beans.get(IntentClient).publish(intent);
platform/messaging: The IntentClient
now uses the same options
object as the MessageClient
to control how to send a message or request. The content of the options
object has not changed, only its name, i.e., migration is only required if assigning it to a typed variable or decorating the IntentClient
.
Note that the communication protocol between host and client has NOT changed, i.e., host and clients can be migrated independently.
To migrate:
IntentOptions
to PublishOptions
(IntentClient#publish
)IntentOptions
to RequestOptions
(IntentClient#request
)platform: Using unique identifier for capability and intention ID introduced a breaking change.
Previously, the IDs used for capabilities and intentions were stable but not unique, which caused problems when deregistering capabilities and intentions. If your application requires stable capability identifiers, you can register a capability interceptor, as follows:
import {Capability, CapabilityInterceptor} from '@scion/microfrontend-platform';
import {Crypto} from '@scion/toolkit/crypto';
import {Beans} from '@scion/toolkit/bean-manager';
Beans.register(CapabilityInterceptor, {
useValue: new class implements CapabilityInterceptor {
public async intercept(capability: Capability): Promise<Capability> {
const stableId = await Crypto.digest(JSON.stringify({
type: capability.type,
qualifier: capability.qualifier,
application: capability.metadata!.appSymbolicName,
}));
return {
...capability,
metadata: {...capability.metadata!, id: stableId},
};
}
},
multi: true
})
Note that the communication protocol between host and client has NOT changed. You can independently upgrade host and clients to the new version.