npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@jamarsto/kiunzi-micro-frontend-tools

v0.0.44

Published

Kiunzi framework Micro-frontend scaffolding

Downloads

3

Readme

Kiunzi Micro-frontend Tools

Kiunzi is a scaffolding framework for building microservice based applications. The Kiunzi Micro-frontend Tools library provides support for Module Federation and Custom Elements to enable the development fully encapsulated micro-frontends

🏠Table of Contents

🎁Acknowledgements

This package uses and is inspired by @angular-architects/module-federation and @angular-architects/module-federation-tools by Manfred Steyer.

🤔Motivation

There were a few things in the angular architects packages that I felt could be expanded and improved on, and I also thought that more could be done with schematics to get a full implementation up and running without multiple tweaks to the generated code.

The key motivation is to simplify adoption of micro-frontends.

🔍Prerequisites

The general foundations:

  • Module Federation requires Webpack 5+
  • Angular's support of Webpack 5 requires Angular 12+
  • This library is built using Angular 13+

Packages used and automatically added to the package.json of the angular workspace when Kiunzi is added.

  • angular-oidc-auth-client
  • @angular-architects/module-federation
  • @angular-architects/module-federation-tools
  • @ng-bootstrap/ng-bootstrap
  • @popperjs/core
  • bootstrap

📦Installation

This library is intended to be used at the start of establishing a project as it updates configurations and generates additional code and configurations. In short it builds the scaffolding.

First, build the example application

# Create your angular workspace
ng new micro-frontend-workspace --create-application false

# Navigate into the micro-frontend-workspace folder
cd micro-frontend-workspace

# Create the shared library
ng generate library --project lib

# Create the shell
ng generate application --no-routing --style sass --project shell

# Create the micro-frontends
ng generate application --no-routing --style sass --project mfe1
ng generate application --no-routing --style sass --project mfe2

# Configure the library
ng add @jamarsto/kiunzi-micro-frontend-tools --project lib --type library --authority <your_oidc_server_url> --client <your_client_id>

# Configure the shell
ng add @jamarsto/kiunzi-micro-frontend-tools --project shell --type shell --port 8000 --library lib

# Configure the micro-frontends
ng add @jamarsto/kiunzi-micro-frontend-tools --project mfe1 --type microfrontend --port 8001 --library lib
ng add @jamarsto/kiunzi-micro-frontend-tools --project mfe2 --type microfrontend --port 8002 --library lib

Next, update the tsconfig.json to add the resolveJsonModule and esModuleInterop flags

{
  "compileOnSave": false,
  "compilerOptions": {
    "resolveJsonModule": true,
    "esModuleInterop": true,

Finally, make sure the library is linked locally so that it is exposed as an npm package to the build

cd projects/lib
npm link
cd ../..
npm link lib

You may need to restart your ide for the tsconfig.json and npm link changes to be picked up

📀Getting Started

Update projects/shell/src/app/app-routing.module.ts to add the modules to customShellRoutes.moduleRoutes

export const customShellRoutes: CustomShellRoutes = {
	headRoutes: [
		{ path: '', redirectTo: 'retail', pathMatch: 'full' },
		{ path: 'unauthorized', component: UnauthorisedComponent }
	],
	moduleRoutes: [
		{ title: 'Module One', name: 'mfe1', prefix: 'one', items: [], guards: [AutoLoginAllRoutesWithRoleGuard], roles: ['ADMIN', 'USER'] },
		{ title: 'Module Two', name: 'mfe2', prefix: 'two', items: [], guards: [AutoLoginAllRoutesWithRoleGuard], roles: ['ADMIN', 'USER'] }
	],
	tailRoutes: [
		{ path: '**', component: NotFoundComponent }
	]
}

Update the src/app/remote-app/remote-app-routing.module.ts for each module to reflect the routing required within the module

const customRoutes: CustomModuleRoutes = {
  headRoutes: [
    { path: '', redirectTo: shellModule.prefix, pathMatch: 'full' },
    { path: 'unauthorized', component: UnauthorisedComponent }
  ],
  moduleRoute: { component: RootComponent, guards: [AutoLoginAllRoutesWithRoleGuard], roles: ['ADMIN', 'USER'], children: [
    { path: '', component: HomeComponent },
    { path: 'example', component: ExampleComponent },
  ]},
  tailRoutes: []
}

Update the src/assets/menu.json for each module to reflect routes we want to add to the shell navigation bar

{
    "menuItems": [
        { "title": "Home", "link": "/", "fullMatch": true },
        { "title": "Example", "link": "/example", "fullMatch": false }
    ]
}

Add a proxy.conf.json to the angular workspace, making sure the entries created match the modules created

{
    "/mfe/mfe1": {
        "target": "http://localhost:8001",
        "pathRewrite": {
            "^/mfe/mfe1/": "/"
        },
        "secure": false,
        "changeOrigin": true
    },
    "/mfe/mfe2": {
        "target": "http://localhost:8002",
        "pathRewrite": {
            "^/mfe/mfe2/": "/"
        },
        "secure": false,
        "changeOrigin": true
    }
}

Add proxyConfig to the serve section of the shell project in angular.json

"serve": {
    "builder": "ngx-build-plus:dev-server",
        "configurations": {
            "production": {
                "browserTarget": "shell:build:production",
                "extraWebpackConfig": "projects/shell/webpack.prod.config.js"
            },
            "development": {
                "browserTarget": "shell:build:development",
                "proxyConfig": "proxy.conf.json"
            }
        },

The modules and shell are now ready to be built and run as normal

✨Development

The shellModule constant in each src/app/remote-app/remote-app-routing.module.ts is used to simulate the shell when testing the micro-frontend in standalone mode

export const shellModule: Module = {name: 'mfe1', title: 'Module One', prefix: 'one', items: jsonMenuItems.menuItems as MenuItems};

The navigation bar in the projects/src/shell/app/component/header/header.component.ts is dynamically generated using the src/assets/menu.json from each module

ngOnInit(): void {
  this.modules.forEach((entry) => this
      .menuItemService
      .getMenuItemsForModule(entry.name)
      .subscribe((children) => entry.items = children));
}

To keep the routes from the shell and modules in sync Kiunzi uses events under the hood. To register the event handling we use syncRouteShell.sync in the constructor of projects/shell/src/app/app.component.ts

constructor(private router: Router, private syncRouteShell: SyncRouteShell) {
  this.syncRouteShell.sync(this.router, customShellRoutes);
}

and we use syncRouteModule.sync in ngOnInit of src/app/remote-app/remote-app.component.ts in each module

ngOnInit(): void {
  this.syncRouteModule.sync(this.router, shellModule.name);
}

📄License

This project is licensed under the MIT license. See the LICENSE