## 创建远程模块 - 1 创建远程模块,远程模块基于vite。 ``` yarn create vite ``` - 2 安装bossjob-remote: ``` yarn add bossjob-remote ``` - 3 在根目录下创建bossjob.config.js 一个工程可以包含多个模块 ``` export default { remotePoints: [ { id: 'chat', // 模块唯一id ssr: false, // 是否启用服务端渲染 roo
npm install bossjob-remote
yarn create vite
`
- 2 安装bossjob-remote:
`
yarn add bossjob-remote
`
- 3 在根目录下创建bossjob.config.js 一个工程可以包含多个模块
`
export default {
remotePoints: [
{
id: 'chat', // 模块唯一id
ssr: false, // 是否启用服务端渲染
root: 'src/chat' // 模块根目录,建议src/[module_id]
},
{
id: 'chat-service',
ssr: false,
root: 'src/chat-service'
}]
}
`- 4 为每个远程模块创建代码文件,以chat为例:
`
// src/chat/index.tsx
import App from "./App"
import { getInitialProps } from 'bossjob-remote/dist/clientStorage'
import React from "react"
import { createRoot } from 'react-dom/client';function render() {
const props = getInitialProps('chat')
const container = document.getElementById('chat');
const root = createRoot(container);
root.render( );
}
render()
`如果启用ssr则改为:
`
// src/chat/index.tsx
import App from "./App"
import { getInitialProps } from 'bossjob-remote/dist/clientStorage'
import React from "react"
import { hydrateRoot } from 'react-dom/client';function render() {
const props = getInitialProps('chat')
const container = document.getElementById('chat');
hydrateRoot(container, );
}
render()
`
界面主节点:`
// src/chat/App.tsx
import React, { useState } from 'react';function App() {
const [count, setCount] = useState(0)
return (
You clicked {count} times
)
}export default App
`
为每个module创建一个html入口文件: src/chat/index.html`
`
如果使用了ssr 还需添加服务器文件用于编译:
`
// src/chat/renderer.js
import { default as serverRenderer} from 'bossjob-remote/dist/serverRenderer'export default serverRenderer
`
开发模式则添加:
`
// src/chat/renderer-dev.js
import { default as serverRenderer} from 'bossjob-remote/dist/serverRenderer-dev'export default serverRenderer
`
在命令行中执行编译:`
bossjob build
`
完成编译后启动服务:`
bossjob start
`
连接远程模块
- 1 主工程中安装bossjob-remote:
`
yarn add bossjob-remote
`
- 2 配置连接器,以next为例
`
// helpers/bossjobRemoteClient
import { getClient } from 'bossjob-remote/dist/client'
import Script from 'next/script'const client = getClient({
parseScript: (script, baseUrl) => {
return key={script.src + script.textContent}
type="module"
async
crossOrigin={'anonymous'}
src={script.src ?
${baseUrl}${script.src} : undefined}>
{script?.textContent?.replaceAll('\n', ';') ?? ''}
},
parseLink: (link, baseUrl) => key={link.href}
rel={link.rel}
href={${baseUrl}${link.href}}>
})export default client
`
- 3 在页面的根layout中连接远程模块,可在同一页面连接多个模块,以chat,third为例,其中third为ssr模块`
app/(chat-page)/layout.tsx
import bossjobClient from 'helpers/bossjobRemoteClient'export default async function PublicLayout(props: any) {
const config = { }
const lang = ''
const chatDictionary = { chat: {}}
const userDetail = {}
const data = {
config,
lang,
chatDictionary: dictionary?.chat ?? {},
chat_id,
userDetail: userDetailRes?.data?.data
}
const chatModule = await bossjobClient.connectModule({
id: 'chat',
baseUrl: 'http://localhost:3000',
initialProps: data, // 传给远程组件初始化的props
initalSharedData: {
CHAT_ID: +chat_id ? chat_id : null,
}
})
const thirdModule = await bossjobClient.connectModule({
id: 'third',
baseUrl: 'http://localhost:3000',
ssr: true
})
return (
{chatModule.inHead}
{thirdModule.inHead}
{thirdModule.inBody}
{chatModule.inBody}
{thirdModule.component}
{chatModule.component}
{children}
)
}`数据通信
- 主工程在连接子模块时可以传递initalProps
`
const data = {
config,
lang,
chatDictionary: dictionary?.chat ?? {},
chat_id,
userDetail: userDetailRes?.data?.data
}
const chatModule = await bossjobClient.connectModule({
id: 'chat',
baseUrl: 'http://localhost:3000',
initialProps: data, // 传给远程组件初始化的props
initalSharedData: {
CHAT_ID: +chat_id ? chat_id : null,
}
})
`
- 子模块可以在入口文件使用getInitialProps接收此状态
`
// src/chat/index.tsx
import App from "./App"
import { getInitialProps } from 'bossjob-remote/dist/clientStorage'
import React from "react"
import { hydrateRoot } from 'react-dom/client';function render() {
const props = getInitialProps('chat')
const container = document.getElementById('chat');
hydrateRoot(container, );
}
render()
`- 每个模块都可以发布共享状态,共享状态由id标记,相同id的状态会覆盖旧数据。
`
import { publishSharedData } from 'bossjob-remote/dist/clientStorage'function publishChatId(chatId) {
publishSharedData('CHAT_ID', chatId)
}
`
其他节点可以用 useSharedData 监听数据变化。
`
import { useSharedData } from 'bossjob-remote/dist/clientStorage'
import { useEffect } from 'react'
const Page = () => {
const chatId = useSharedData('CHAT_ID')
useEffect(() => {
...
}, [chatId]) return (
<>
>
);
}
export default Page
`其他节点可以用 useSharedData 监听数据变化。
`
import { watchSharedData } from 'bossjob-remote/dist/clientStorage'
function watchChatIdChange() {
watchSharedData('CHAT_ID', (newChatId) => {
...
});
}
export default Page
``