diff --git a/docs/core-concepts.mdx b/docs/core-concepts.mdx
index f44a82c..b294341 100644
--- a/docs/core-concepts.mdx
+++ b/docs/core-concepts.mdx
@@ -549,39 +549,46 @@ from it.
## Micro-Frontends
-Some content is not known at render time and must be loaded from another service. The v5
-`mfe()` builder embeds a _micro-frontend_: an HTML fragment fetched from a remote URL,
-supporting both server-side rendering (SSR) and client-side rendering (CSR) with optional
-event wiring between fragments. It requires a view built with `mfeEnabled(true)`.
+A micro-frontend architecture splits a page into HTML **fragments** owned by independent services.
+With v5, a _shell_ (view) page can be created with the new `mfe()` builder.
+This builder embeds a micro-frontend based on metadata set in the _configuration_ object.
+Each HTML fragment is fetched remotely from the URL configured in the metadata.
+The composition of the micro-frontends is done by a client side
+script that is required to be set in the view.
+The _mfe_ feature requires a view built with `mfeEnabled(true)`.
+
+### Setup
+
+1. Build the shell view with `mfeEnabled(true)`.
+2. Add the HtmlFlow MFE engine in `
` element of the page.
+3. Declare the micro-frontends in the view with `mfe()` method.
```java
-HtmlView> view = HtmlFlow.ViewFactory.builder()
+static final String ENGINE =
+ "https://cdn.jsdelivr.net/gh/xmlet/HtmlFlow@development/htmlflow-mfe-engine/dist/htmlflow-mfe-engine.js";
+
+HtmlView> shell = HtmlFlow.ViewFactory.builder()
.mfeEnabled(true)
.build()
.view(page -> page
.html()
- .head().__()
+ .head()
+ .script().attrType(EnumTypeScriptType.MODULE).attrSrc(ENGINE).__()
+ .__() // head
.body()
- .div()
- .mfe(cfg -> {
- cfg.setMfeUrlResource("http://localhost:8081/bikes");
- cfg.setMfeName("mfe1");
- cfg.setMfeElementName("some-element");
- cfg.setMfeListeningEventName("triggerBikeEvent");
- cfg.setMfeTriggersEventName("triggerCartEvent");
- cfg.setMfeScriptUrl("http://localhost:8081/js/mfe-bikes.js");
- cfg.setMfeStylingUrl("http://localhost:8081/css/style.css");
- })
- .__() // div
+ .mfe(cfg -> cfg
+ .setMfeUrlResource("http://localhost:8081/bikes/view")
+ .setMfeName("bikes")
.__() // body
.__() // html
);
```
-
+
+
The Kotlin DSL has no sugar for `mfeEnabled`, so build the view through the same
@@ -590,32 +597,299 @@ The Kotlin DSL has no sugar for `mfeEnabled`, so build the view through the same
```kotlin
import htmlflow.*
-val view: HtmlView<*> = HtmlFlow.ViewFactory.builder()
+const val ENGINE =
+ "https://cdn.jsdelivr.net/gh/xmlet/HtmlFlow@development/htmlflow-mfe-engine/dist/htmlflow-mfe-engine.js"
+
+val shell: HtmlView<*> = HtmlFlow.ViewFactory.builder()
.mfeEnabled(true)
.build()
.view { page ->
page.html {
- head { }
+ head {
+ script { attrType(EnumTypeScriptType.MODULE); attrSrc(ENGINE) }
+ }
body {
- div {
- mfe { cfg ->
- cfg.setMfeUrlResource("http://localhost:8081/bikes")
- cfg.setMfeName("mfe1")
- cfg.setMfeElementName("some-element")
- cfg.setMfeListeningEventName("triggerBikeEvent")
- cfg.setMfeTriggersEventName("triggerCartEvent")
- cfg.setMfeScriptUrl("http://localhost:8081/js/mfe-bikes.js")
- cfg.setMfeStylingUrl("http://localhost:8081/css/style.css")
- }
- } // div
- } // body
- } // html
+ mfe { cfg ->
+ cfg.setMfeUrlResource("http://localhost:8081/bikes/view")
+ cfg.setMfeName("bikes")
+ }
+ }
+ }
}
```
+The engine fetches fragments and stylesheets from the browser, therefore services on another origin must
+allow CORS requests from the shell.
+
+:::warning
+When configuring a micro-frontend the url and the name are mandatory (see [MFE Configuration](#micro-frontend-configuration)).
+:::
+Rendering the view `shell.render()` produces the placeholder markup:
+
+```html
+
+
+
+
+
+
+
+
+```
+
+The micro-frontend mechanism expects any HTML fragments.
+It can come from HtmlFlow, Thymeleaf, or any other template engine as long as HTML is provided.
+Is it possible to combine server-side rendering (SSR) and client-side rendering (CSR) fragments,
+an example is shown [here](#micro-frontend-configuration)).
+
+### Micro-frontend configuration
+
+The configuration object passed to the mfe method has the following properties:
+| Option | Purpose |
+| ------------------------------------- | ---------------------------------------------------------------------------------------- |
+| `setMfeUrlResource(url)` **required** | URL that represents the location of HTML fragment. |
+| `setMfeName(name)` **required** | Unique name of the micro-frontend, used by `window.mfe(...)` in scripts. |
+| `setMfeScriptUrl(url)` | Fragment script used for hydration, added to `` as `
+```
+
+If the hash script does not match the provided hash, the browser will refuse to execute it.
+
+:::tip Full example
+[HtmlFlow-Microfrontend-Examples](https://github.com/xmlet/HtmlFlow-Microfrontend-Examples) is a
+runnable webshop with a shell and bikes, cart, and order services. It demonstrates events,
+reloading, shared theming, and streaming.
+:::
+
For content that arrives **asynchronously** (reactive streams, futures, or Kotlin suspend
functions) and for streaming the HTML out progressively, see
[Advanced → Asynchronous Rendering](/docs/advanced#asynchronous-rendering) and