Skip to content

Latest commit

 

History

History
429 lines (385 loc) · 13.8 KB

08-getting-started-browse-capabilities.md

File metadata and controls

429 lines (385 loc) · 13.8 KB

SCION Microfrontend Platform

SCION Microfrontend Platform Projects Overview Changelog Contributing Sponsoring

SCION Microfrontend Platform > Getting Started > Browse Catalog of Capabilities

In this chapter, we will browse the catalog of capabilities to dynamically construct the top-level navigation.

Prepare the microfrontends for contributing to the navigation bar

In chapter 6, we already provided the ProductList Microfrontend as microfrontend capability. We now need to do the same for the CustomerList Microfrontend.

  1. Open the manifest customers-app/src/manifest.json of the Customers App.

  2. Register the CustomerList Microfrontend as microfrontend capability, as follows:

         {
           "name": "Customers App",
           "capabilities": [
    [+]      {
    [+]        "type": "microfrontend",
    [+]        "qualifier": {
    [+]          "entity": "customers"
    [+]        },
    [+]        "private": false,
    [+]        "properties": {
    [+]          "path": "/customer-list/customer-list.html",
    [+]          "navbar": {
    [+]            "label": "Customers"
    [+]          }
    [+]        }
    [+]      },
             {
               "type": "microfrontend",
               "qualifier": {
                 "entity": "customer"
               },
               "params": [
                 {
                   "name": "id",
                   "required": true
                 }
               ],
               "properties": {
                 "path": "/customer/customer.html#?id=:id",
                 "outlet": "aside"
               }
             }
           ],
           "intentions": [
             {
               "type": "microfrontend",
               "qualifier": {
                 "entity": "products"
               }
             }
           ]
         }

    Note that we set the custom property navbar in the properties section of the capability. We will read this property when filtering the catalog of capabilities to determine for which microfrontends to create a navbar item.

  3. Open the manifest products-app/src/manifest.json of the Products App and add the property navbar to the ProductList Microfrontend, as follows:

         {
           "name": "Products App",
           "capabilities": [
             {
               "type": "microfrontend",
               "qualifier": {
                 "entity": "products"
               },
               "params": [
                 {
                   "name": "ids",
                   "required": false
                 }
               ],
               "private": false,
               "properties": {
                 "path": "/product-list/product-list.html#?ids=:ids",
    [+]          "navbar": {
    [+]            "label": "Products"
    [+]          }
               }
             },
             {
               "type": "microfrontend",
               "qualifier": {
                 "entity": "product"
               },
               "params": [
                 {
                   "name": "id",
                   "required": true
                 }
               ],
               "properties": {
                 "path": "/product/product.html#?id=:id",
                 "outlet": "aside"
               }
             }
           ]
         }
Declare intention to browse microfrontend capabilities

In order for the host app to browse and navigate to microfrontend capabilities, we need to declare an intention, as follows:

  1. Open the file host-app/src/host.ts.
  2. Declare a microfrontend wildcard intention, as follows:
         await MicrofrontendPlatformHost.start({
           applications: [
             {symbolicName: 'products-app', manifestUrl: 'http://localhost:4201/manifest.json'},
             {symbolicName: 'customers-app', manifestUrl: 'http://localhost:4202/manifest.json'},
             {
               symbolicName: 'devtools',
               manifestUrl: 'https://microfrontend-platform-devtools.scion.vercel.app/manifest.json',
               intentionCheckDisabled: true,
               scopeCheckDisabled: true,
             },
           ],
           host: {
             manifest: {
               name: 'Host App',
               intentions: [
                 {type: 'microfrontend', qualifier: {component: 'devtools', vendor: 'scion'}},
    [+]          {type: 'microfrontend', qualifier: {'*': '*'}},
               ],
             },
           },
         });
Remove static navigation buttons
  1. Open the file host-app/src/index.html of the host app.

  2. Remove the buttons in the <nav> element, as follows:

    Before:

     <nav>
       <button id="products">Products</button>
       <button id="customers">Customers</button>
     </nav>

    After:

    <nav></nav>
  3. Open the file host-app/src/host.ts of the host app.

  4. Remove the event listeners of the static buttons we removed in the previous step.

Populate the navigation bar
  1. Open the file host-app/src/host.ts of the host app.
  2. Create a button for each of the microfrontend capabilities to be added to the navigation bar, as follows:
[+]   import {ManifestService, MicrofrontendPlatformHost, OutletRouter} from '@scion/microfrontend-platform';
      import {Beans} from '@scion/toolkit/bean-manager';
[+]   import {filterArray} from '@scion/toolkit/operators';

      public async init(): Promise<void> {
        await MicrofrontendPlatformHost.start({
          applications: [
            {symbolicName: 'products-app', manifestUrl: 'http://localhost:4201/manifest.json'},
            {symbolicName: 'customers-app', manifestUrl: 'http://localhost:4202/manifest.json'},
            {
              symbolicName: 'devtools',
              manifestUrl: 'https://microfrontend-platform-devtools.scion.vercel.app/manifest.json',
              intentionCheckDisabled: true,
              scopeCheckDisabled: true,
            },
          ],
          host: {
            manifest: {
              name: 'Host App',
              intentions: [
                {type: 'microfrontend', qualifier: {component: 'devtools', vendor: 'scion'}},
                {type: 'microfrontend', qualifier: {'*': '*'}},
              ],
            },
          },
        });
    
        // Display the DevTools
        Beans.get(OutletRouter).navigate({component: 'devtools', vendor: 'scion'}, {outlet: 'bottom'});

[+]     // Create a navigation button for each of the microfrontend capabilities to be added to the navigation bar
[+]     const navbar = document.querySelector('nav');
[+]     Beans.get(ManifestService).lookupCapabilities$({type: 'microfrontend'})
[+]       .pipe(filterArray(capability => capability.properties.navbar))
[+]       .subscribe(capabilities => {
[+]         navbar.innerHTML = null;
[+]         capabilities.forEach(capability => {
[+]           const menuItem = navbar.appendChild(document.createElement('button'));
[+]           menuItem.innerText = capability.properties.navbar.label;
[+]           menuItem.addEventListener('click', () => {
[+]             Beans.get(OutletRouter).navigate(capability.qualifier);
[+]           });
[+]         })
[+]       });

Using the ManifestServie, we can browse the catalog of capabilities and pass a filter to return only the capabilities that are of interest to us. We further filter capabilities having the navbar property. For each of these capabilities, we create a button that, when clicked, navigates to the microfrontend of that qualifier.

Open the app in the browser

We did it! Run npm run start to serve the applications and see that the navigation buttons are now contributed via capabilities.

What we did in this chapter

In this chapter, we learned how to browse the catalog of capabilities to dynamically populate the navigation bar.

The customers-app/src/manifest.json looks as following:
{
  "name": "Customers App",
  "capabilities": [
    {
      "type": "microfrontend",
      "qualifier": {
        "entity": "customers"
      },
      "private": false,
      "properties": {
        "path": "/customer-list/customer-list.html",
        "navbar": {
          "label": "Customers"
        }
      }
    },
    {
      "type": "microfrontend",
      "qualifier": {
        "entity": "customer"
      },
      "params": [
        {
          "name": "id",
          "required": true
        }
      ],
      "properties": {
        "path": "/customer/customer.html#?id=:id",
        "outlet": "aside"
      }
    }
  ],
  "intentions": [
    {
      "type": "microfrontend",
      "qualifier": {
        "entity": "products"
      }
    }
  ]
}
The products-app/src/manifest.json looks as following:
{
  "name": "Products App",
  "capabilities": [
    {
      "type": "microfrontend",
      "qualifier": {
        "entity": "products"
      },
      "params": [
        {
          "name": "ids",
          "required": false
        }
      ],
      "private": false,
      "properties": {
        "path": "/product-list/product-list.html#?ids=:ids",
        "navbar": {
          "label": "Products"
        }
      }
    },
    {
      "type": "microfrontend",
      "qualifier": {
        "entity": "product"
      },
      "params": [
        {
          "name": "id",
          "required": true
        }
      ],
      "private": true,
      "properties": {
        "path": "/product/product.html#?id=:id",
        "outlet": "aside"
      }
    }
  ]
}
The host-app/src/index.html looks as following:
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Getting Started with SCION</title>
    <link rel="stylesheet" type="text/css" href="host.scss">
    <script type="module" src="./host.ts"></script>
  </head>
  <body>
    <nav></nav>
    <main>
      <sci-router-outlet></sci-router-outlet>
      <sci-router-outlet name="aside"></sci-router-outlet>
      <sci-router-outlet name="bottom"></sci-router-outlet>
    </main>
  </body>
</html>
The host-app/src/host.ts looks as following:
import {ManifestService, MicrofrontendPlatformHost, OutletRouter} from '@scion/microfrontend-platform';
import {Beans} from '@scion/toolkit/bean-manager';
import {filterArray} from '@scion/toolkit/operators';

class HostController {

  public async init(): Promise<void> {
    await MicrofrontendPlatformHost.start({
      applications: [
        {symbolicName: 'products-app', manifestUrl: 'http://localhost:4201/manifest.json'},
        {symbolicName: 'customers-app', manifestUrl: 'http://localhost:4202/manifest.json'},
        {
          symbolicName: 'devtools',
          manifestUrl: 'https://microfrontend-platform-devtools.scion.vercel.app/manifest.json',
          intentionCheckDisabled: true,
          scopeCheckDisabled: true,
        },
      ],
      host: {
        manifest: {
          name: 'Host App',
          intentions: [
            {type: 'microfrontend', qualifier: {component: 'devtools', vendor: 'scion'}},
            {type: 'microfrontend', qualifier: {'*': '*'}},
          ],
        },
      },
    });

    // Display the DevTools
    Beans.get(OutletRouter).navigate({component: 'devtools', vendor: 'scion'}, {outlet: 'bottom'});

    // Create a navigation button for each of the microfrontend capabilities to be added to the navigation bar
    const navbar = document.querySelector('nav');
    Beans.get(ManifestService).lookupCapabilities$({type: 'microfrontend'})
      .pipe(filterArray(capability => capability.properties.navbar))
      .subscribe(capabilities => {
        navbar.innerHTML = null;
        capabilities.forEach(capability => {
          const menuItem = navbar.appendChild(document.createElement('button'));
          menuItem.innerText = capability.properties.navbar.label;
          menuItem.addEventListener('click', () => {
            Beans.get(OutletRouter).navigate(capability.qualifier);
          });
        })
      });
  }
}

new HostController().init();
What's next

You have now learned the core concepts of the SCION Microfrontend Platform. Click here for a summary and further reading.