@sigma-streaming/micro
v1.1.3
Published
CMS micro frontend integration package
Downloads
130
Maintainers
Readme
Sigma Streaming Micro Frontend
Installation
npm
npm install @sigma-streaming/micro wujie-react
yarn
yarn add @sigma-streaming/micro wujie-react
pnpm
pnpm install @sigma-streaming/micro wujie-react
Usage
1. Register Sigma Apps
main.tsx
import type { AppConfig, MicroApp } from '@sigma-streaming/micro'
import { registerSigmaApps } from '@sigma-streaming/micro'
export const microApps: MicroApp[] = [
{
name: '@sigma-streaming/ssai',
url: '//123.31.18.25:2181/micro/cms/ssai/',
},
{
name: '@sigma-streaming/lrm',
url: '//dev-livestream.gviet.vn/micro/cms/lrm/',
},
]
const appConfig: AppConfig = {
// generated token for sigma micro app
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
// token type
tokenProp: 'x-backdoor',
// App channel ID - Optional - For tokenType Bearer
appId: 'c9c2ebfb-...',
}
export const actions = registerSigmaApps(microApps, appConfig)
2. Create component for Micro App
LrmApp.tsx
import React from 'react'
import WujieReact from 'wujie-react'
import { useHistory, useLocation } from 'react-router-dom'
export default function LrmApp(
{
url = '//dev-livestream.gviet.vn/micro/cms/lrm/',
name = '@sigma-streaming/lrm'
}: MicroProps) {
const location = useLocation()
// const navigation = useNavigate(); // new react-router
const history = useHistory()
const mainPath = '/lrm'
const subPath = '/lrm-sub'
const path = location.pathname.replace(subPath, '').replace(mainPath, '').replace('/', '')
const viteUrl = url + path
const props = {
jump: (newRoute) => {
history.replace(`/${newRoute}`)
},
}
return (
// Single mode, Name is the same to reuse an unbounded instance,
// changing the URL sub-application re-rendering instance to the corresponding routing
<WujieReact
width="100%"
height="100%"
name={name}
url={viteUrl}
sync={true}
props={props}
></WujieReact>
)
}
3. Create container and add route corresponding for each app's activeRule
*** Note: We use tailwind css class to demonstrate layout styling App.tsx
import { Route, HashRouter as Router, Switch } from 'react-router-dom'
import { CONTAINER } from './main'
import LrmApp from './LrmApp'
// Usecase 1: Main path
<div className="relative my-[-15px] min-h-[calc(100vh-45px)] mx-[-20px]">
<Switch>
<Route exact path="/lrm"><LrmApp /></Route>
<Route exact path="/ssai"></Route>
</Switch>
</div>
// Usecase 2: With sub path
<div className="relative my-[-15px] min-h-[calc(100vh-45px)] mx-[-20px]">
<Switch>
<Route exact path="/lrm"><LrmApp /></Route>
<Route exact path="/lrm-sub/:path"><LrmApp /></Route>
<Route exact path="/ssai"></Route>
</Switch>
</div>
// Usecase 3: Sub path only
<div className="relative my-[-15px] min-h-[calc(100vh-45px)] mx-[-20px]">
<Switch>
<Route exact path="/lrm-sub/:path"><LrmApp /></Route>
<Route exact path="/ssai-sub/:path"></Route>
</Switch>
</div>
4. Add routing to each app to your Main Sidebar
Each app expose a routes and list
Sidebar.tsx
import type { GlobalState } from '@sigma-streaming/micro'
import type { MenuProps } from 'antd'
import { Menu } from 'antd'
import { actions } from './main'
const Sidebar = (props: SidebarProps) => {
const history = useHistory()
const [state, setState] = useState<GlobalState>()
useEffect(() => {
const cleanUp = actions.onStateChange((newState) => {
setState(newState)
})
return () => { cleanUp() }
}, [])
// Render sidebar from state children
// Ant design example
type MenuItem = Required<MenuProps>['items'][number]
function getItem(
label: React.ReactNode,
key: React.Key,
icon?: React.ReactNode,
children?: MenuItem[],
type?: 'group',
): MenuItem {
return {
key,
icon,
children,
label,
type,
} as MenuItem
}
const memoItems = useMemo(() => {
const items: MenuProps['items'] = (state?.children || []).map(item =>
getItem(item.name, item.name, <div className="i-ant-design:mail-filled" />,
item.routes.map(route => getItem(route.meta.title, route.path, <div className={route.meta.icon} />))
),
)
return items
}, [state])
const onClick: MenuProps['onClick'] = (e) => {
const path = `/${e.keyPath[1]}-sub${e.keyPath[0]}`
if (e.keyPath)
history.push(path)
}
return (
<Menu
className="flex-1"
onClick={onClick}
style={{ width: 220 }}
mode="inline"
items={memoItems}
/>
)
}