-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e1eacf2
commit 3d42c45
Showing
10 changed files
with
258 additions
and
17 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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 |
---|---|---|
@@ -1,3 +1,37 @@ | ||
# Environment Configuration | ||
|
||
... | ||
Runtime configuration works different for micro frontends. This is mostly true due to the fact that micro frontends are distributed, whereas the classic way is a configuration found at a central location such as a file or a some environment variables at a single server. | ||
|
||
Nevertheless, at the end all configuration (like the rest of the code) has to end up in the application. Therefore, the configuration is assumed to be coming *with* the micro frontend. For this we rely on the response from the micro frontend discovery service (e.g., the Piral Cloud Feed Service) to also bring in configuration. | ||
|
||
The Piral framework takes care of understanding the discovery service response and dispatching the delivered configuration to the micro frontend. In the micro frontend you can obtain the configuration via the `IMfService` or `IMfAppService` instances, e.g., passed into the setup lifecycle: | ||
|
||
```cs | ||
public class Module : IMfModule | ||
{ | ||
public Task Setup(IMfAppService app) | ||
{ | ||
// use: app.Meta.Config | ||
} | ||
|
||
public Task Teardown(IMfAppService app) | ||
{ | ||
} | ||
|
||
public void Configure(IServiceCollection services) | ||
{ | ||
} | ||
} | ||
``` | ||
|
||
As the discovery service might set the configuration for published micro frontends, the debug issue for local development still exists. How do you get in configuration in here? | ||
|
||
To make local development work you can add a `config.json` file to your micro frontend, which has to be copied to the output directory. This file can now contain a valid configuration as JSON: | ||
|
||
```json | ||
{ | ||
"foo": "bar" | ||
} | ||
``` | ||
|
||
This file is automatically picked up by the emulator when you start debugging your micro frontend. |
This file contains 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,88 @@ | ||
# Standard Micro Frontend Service | ||
|
||
Every pilet gets automatically a service called `IMfService` injected. | ||
|
||
[[toc]] | ||
|
||
## Events | ||
|
||
You can use the `IMfService` service to emit and receive events via the standard API event bus. This is great for doing loosely-coupled MF-to-MF communication. | ||
|
||
Example: | ||
|
||
```razor | ||
@inject IMfService ps | ||
@implements IDisposable | ||
<aside class=@_sidebarClass> | ||
<a @onclick=@CloseSidebar style="display: inline-block; padding: 0 10px; cursor: pointer;">x</a> | ||
</aside> | ||
@code { | ||
[Parameter] | ||
public bool IsOpen { get; set; } = false; | ||
[Parameter] | ||
public EventCallback<bool> IsOpenChanged { get; set; } | ||
string _sidebarClass { get => IsOpen ? "sidebar open" : "sidebar"; } | ||
public void Dispose() | ||
{ | ||
ps.RemoveEventListener<bool>("toggle-sidebar", ToggleSidebar); | ||
} | ||
protected override void OnInitialized() | ||
{ | ||
ps.AddEventListener<bool>("toggle-sidebar", ToggleSidebar); | ||
} | ||
public void ToggleSidebar(bool value) => IsOpenChanged.InvokeAsync(value); | ||
public void CloseSidebar() => ToggleSidebar(false); | ||
} | ||
``` | ||
|
||
Another component can now trigger this by using `ps.DispatchEvent("toggle-sidebar", false);` with an injected `@inject IMfService ps`. | ||
|
||
## Sharing Data | ||
|
||
The `IMfService` can be used to access some shared memory storage. The functions `TrySetData` and `TryGetData` can be used to set and get data on the shared storage. | ||
|
||
Here's an example: | ||
|
||
```razor | ||
@inject IMfService ps | ||
<button @onclick=@StoreValue>Store some value</button> | ||
<button @onclick=@LogValue>Log current value</button> | ||
@code { | ||
public async void StoreValue() | ||
{ | ||
if (ps.TrySetData<string>("myValue", "Hello World!")) | ||
{ | ||
Console.WriteLine("Stored new value: {0}", value); | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Could not store value."); | ||
} | ||
} | ||
public async void LogValue() | ||
{ | ||
if (ps.TryGetData<string>("myValue", out var value)) | ||
{ | ||
Console.WriteLine("Currently stored value is: {0}", value); | ||
} | ||
else | ||
{ | ||
Console.WriteLine("Currently nothing stored."); | ||
} | ||
} | ||
} | ||
``` | ||
|
||
Note that only the micro frontend that initially wrote the data is capable of updating it. Conflicts are therefore avoided by giving only a single micro frontend right access - following the first-write-claims-ownership principle. |
This file contains 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 |
---|---|---|
@@ -1,3 +1,33 @@ | ||
# Environment Configuration | ||
|
||
... | ||
Runtime configuration works different for micro frontends. This is mostly true due to the fact that micro frontends are distributed, whereas the classic way is a configuration found at a central location such as a file or a some environment variables at a single server. | ||
|
||
Nevertheless, at the end all configuration (like the rest of the code) has to end up in the application. Therefore, the configuration is assumed to be coming *with* the micro frontend. For this we rely on the response from the micro frontend discovery service (e.g., the Piral Cloud Feed Service) to also bring in configuration. | ||
|
||
The Piral framework takes care of understanding the discovery service response and dispatching the delivered configuration to the micro frontend. In the micro frontend you can obtain the configuration via the `IConfiguration` passed into the `ConfigureServices` section: | ||
|
||
```cs | ||
public class Module | ||
{ | ||
public static void Main() {} | ||
|
||
public static void ConfigureServices(IServiceCollection services, IConfiguration configuration) | ||
{ | ||
// Use IConfiguration | ||
} | ||
} | ||
``` | ||
|
||
As the discovery service might set the configuration for published micro frontends, the debug issue for local development still exists. How do you get in configuration in here? | ||
|
||
To make local development work you can enhance the response of the local debug server (mocking a micro frontend discovery service). With the `meta.json` file you can add additional sections to the micro frontend's meta data: | ||
|
||
```json | ||
{ | ||
"config": { | ||
"foo": "bar" | ||
} | ||
} | ||
``` | ||
|
||
Using this content you added a `config` section to the meta response of the local debug server returning you the provided configuration *locally*. |
This file contains 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,51 @@ | ||
# HTTP Interceptors | ||
|
||
Pilets can add *global* HTTP interceptors, which will be triggered for all HTTP requests using the *global* `HttpClient`. This can be done by adding a singleton `IHttpInterceptor` to the services, e.g.: | ||
|
||
```cs | ||
public class Module | ||
{ | ||
public static void Main() {} | ||
|
||
public static void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddSingleton<IHttpInterceptor, MyInterceptor>(); | ||
} | ||
} | ||
``` | ||
|
||
The interceptor itself has methods to react to a request (before sending the actual request) or response (after receiving the response). | ||
|
||
```cs | ||
class MyInterceptor : IHttpInterceptor | ||
{ | ||
public Task<HttpRequestMessage> OnRequest(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
// Add some header | ||
request.Headers.Add("x-foo-bar", "other"); | ||
return Task.FromResult(request); | ||
} | ||
|
||
public Task<HttpResponseMessage> OnResponse(HttpResponseMessage response, CancellationToken cancellationToken) | ||
{ | ||
// Don't do anything | ||
return Task.FromResult(response); | ||
} | ||
} | ||
``` | ||
|
||
In case you want to intercept calls for injecting a bearer token obtained from calling the `getAccessCode()` pilet API you can just add a simple convenience service: | ||
|
||
```cs | ||
public class Module | ||
{ | ||
public static void Main() {} | ||
|
||
public static void ConfigureServices(IServiceCollection services) | ||
{ | ||
services.AddAccessCodeInterceptor(); | ||
} | ||
} | ||
``` | ||
|
||
This way the current access code is retrieved and inserted into the request via the `Authorization` header. |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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 |
---|---|---|
@@ -1,18 +1,24 @@ | ||
namespace Piral.Blazor.Shared | ||
using System.Text.Json.Nodes; | ||
|
||
namespace Piral.Blazor.Shared; | ||
|
||
/// <summary> | ||
/// Contains details about a micro frontend. | ||
/// </summary> | ||
public record MfDetails | ||
{ | ||
/// <summary> | ||
/// Contains details about a micro frontend. | ||
/// Gets the name of the micro frontend. | ||
/// </summary> | ||
public record MfDetails | ||
{ | ||
/// <summary> | ||
/// Gets the name of the micro frontend. | ||
/// </summary> | ||
public required string Name { get; init; } | ||
public required string Name { get; init; } | ||
|
||
/// <summary> | ||
/// Gets the version of the micro frontend. | ||
/// </summary> | ||
public required string Version { get; init; } | ||
} | ||
/// <summary> | ||
/// Gets the version of the micro frontend. | ||
/// </summary> | ||
public required string Version { get; init; } | ||
|
||
/// <summary> | ||
/// Gets the configuration of the micro frontend. | ||
/// </summary> | ||
public required JsonObject Config { get; init; } | ||
} |