Skip to content

one-more/micro-frontends

Repository files navigation

micro-frontends

Micro-frontends help you to use multiple frameworks on your application. You can apply several frameworks on one page, per each component.

index.ts

import {define} from "@micro-frontends/core";
import {XLink} from "@micro-frontends/framework";
import {XContent} from "@micro-frontends/framework";

// define web-components 
define(XLink);
define(XContent);

index.html

<main>
  <navigation>
    <ul class="margin-top-1em nav flex-column" >
      <li class="nav-item">
        <x-link
            class="nav-link"
            href="/clock"
            text="clock (react & svelte)" >
        </x-link>
      </li>
      <li class="nav-item">
        <x-link
            class="nav-link"
            href="/chat"
            text="chat (svelte + react + vue)" >
        </x-link>
      </li>
      <li class="nav-item">
        <x-link
            class="nav-link"
            href="/todo"
            text="todo (imba)" >
        </x-link>
      </li>
    </ul>
  </navigation>

  <section>
    <x-content id="main" default="main" ></x-content>
  </section>
</main>

x-link router link provide access for src/pages/ where you can build SPA pages x-content pages render content

// Web component defenition
import {Component} from "@micro-frontends/core";

// For React and Vue render
import {renderReact, renderVue} from "@micro-frontends/framework";

Example of the component

React

export class XClockReact extends Component {
    static getName(): string {
        return 'x-clock-react'
    }

    render(root: HTMLDivElement) {
        renderReact(
            <Clock />,
            root,
        )
    }
}

class Clock extends React.Component {
    state = {
        time: new Date(),
    };
    interval: number;

    componentDidMount(): void {
        this.interval = setInterval(() => {
            this.setState({
                time: new Date()
            })
        }, 1000)
    }

    componentWillMount(): void {
        clearInterval(this.interval)
    }

    render(): React.ReactElement<any, string | React.JSXElementConstructor<any>> | string | number | {} | React.ReactNodeArray | React.ReactPortal | boolean | null | undefined {
        return (
            <div>{this.state.time.toLocaleString()}</div>
        )
    }
}

Vue

import {Component} from "@micro-frontends/core";
import ChatClient from "./chat-client.vue"
import {renderVue} from "@micro-frontends/framework";

export class XChatClientVue extends Component {
    static getName(): string {
        return 'x-chat-client-vue'
    }

    render(root: HTMLDivElement) {
        renderVue(
            ChatClient,
            root,
        )
    }
}

chat-client.vue

<template>
    <form class="chat-form" v-on:submit="onSubmit" >
        <div class="form-group">
            <label for="name">name:</label>
            <input
                id="name"
                type="text"
                class="form-control"
                required
                v-model="name"
            >
        </div>
        <div class="form-group" >
            <label for="text">text</label>
            <textarea
                name="text"
                id="text"
                cols="30"
                rows="10"
                class="form-control"
                required
                v-model="text"
            ></textarea>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</template>

<script>
    import {store} from "~/store";
    import {xChatActions} from "~/modules/x-chat";

    export default {
        data() {
            return {
                name: "",
                text: ""
            }
        },
        methods: {
            onSubmit(event) {
                event.preventDefault();

                store.dispatch(
                    xChatActions.sendMessage(
                        this.name + "(vue)",
                        this.text,
                        "right",
                    ),
                );

                this.text = "";
            }
        }
    }
</script>

Component with the standart render way

import {Component} from "@micro-frontends/core";
import Clock from "./clock.svelte";

export class XClockSvelte extends Component {
    static getName() {
        return 'x-clock-svelte'
    }

    render(root) {
        new Clock({
            target: root,
        })
    }
}

clock.svelte

<script>
    import { onMount } from 'svelte';

    let time = new Date();

    // these automatically update when `time`
    // changes, because of the `$:` prefix
    $: hours = time.getHours();
    $: minutes = time.getMinutes();
    $: seconds = time.getSeconds();

    onMount(() => {
        const interval = setInterval(() => {
            time = new Date();
        }, 1000);

        return () => {
            clearInterval(interval);
        };
    });
</script>

<style>
 /* styles here */
</style>

<svg viewBox='-50 -50 100 100'>
    <circle class='clock-face' r='48'/>

	<!-- markers -->
    {#each [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55] as minute}
        <line
                class='major'
                y1='35'
                y2='45'
                transform='rotate({30 * minute})'
        />

        {#each [1, 2, 3, 4] as offset}
            <line
                    class='minor'
                    y1='42'
                    y2='45'
                    transform='rotate({6 * (minute + offset)})'
            />
        {/each}
    {/each}

    <!-- hour hand -->
    <line
            class='hour'
            y1='2'
            y2='-20'
            transform='rotate({30 * hours + minutes / 2})'
    />

	<!-- minute hand -->
    <line
            class='minute'
            y1='4'
            y2='-30'
            transform='rotate({6 * minutes + seconds / 10})'
    />

	<!-- second hand -->
    <g transform='rotate({6 * seconds})'>
        <line class='second' y1='10' y2='-38'/>
        <line class='second-counterweight' y1='10' y2='2'/>
    </g>
</svg>

You need to define all components on the page

chat.ts

import {define} from "@micro-frontends/core";
import {XChatClientSvelte, XChatDisplay} from "~/modules/x-chat";
import {XChatClientVue} from "~/modules/x-chat/components/x-chat-client-vue";

define(XChatClientSvelte);
define(XChatDisplay);
define(XChatClientVue);

Then just use it by the way of web-components

<script src="/chat.bundle.js"></script>

<div id="main">
    <div class="chat">
        <x-chat-client-svelte></x-chat-client-svelte>
        <x-chat-display></x-chat-display>
        <x-chat-client-vue></x-chat-client-vue>
    </div>
</div>

In chat.html you can define a <script src="/chat.bundle.js"></script> section expected to includes on the page

See more examples on micro-frontends-starter

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published