# 快速开始
# 子应用开发者
# 安装编译插件
npm install @jmodule/plugin-webpack
TIP
请先检查项目依赖:webpack@4.x 或 webpack@5.x
# 子应用定义
以vue3为例,在项目入口文件中添加 JModule.define('xxx', {...});
完整示例参考 child-app-vue3 (opens new window)
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App);
if (window.__JMODULE_HOST__) {
// 以自应用模式启动
JModule.define('childAppVue3', {
mount(module, el, stats) {
if (stats.mountTimes === 0) {
app.mount(el);
}
},
});
} else {
// 应用自启动
app.mount('#app')
}
其它框架参考示例:
TIP
- 具体规则定义,依赖宿主应用规约。文档中的字段规约与项目 demo (opens new window) 中一致。
- 比如demo 中的路由模式,前端框架依赖宿主应用的实现。
# 配置编译插件
// .jmodule.conf.js
module.exports = {
mode: 'modules',
devConfig: process.env.NODE_ENV === 'development' ? {
modulesConfig: {
childAppVue3: {
type: 'app',
name: 'Vue3 的子应用',
},
},
currentServer: 'http://localhost:8080', // 当前子应用开发服务地址
platformServer: 'http://localhost:3002', // 宿主应用服务地址
platformLocalPort: '8090', // 集成调试服务端口,在这个端口可进行集成开发调试
onAllServerReady: () => { // 自动探测服务,当所有服务正常启动后执行
console.log(
chalk.green('\n\t已启动集成服务: '),
chalk.cyanBright(`http://localhost:${platformLocalPort}/`),
'\n',
);
},
} : undefined,
}
- 构建完成,项目中将自动生成 index.js 文件,即为接入宿主应用的入口文件
- 开发过程中,通过访问 platformLocalPort 定义的端口,可以在宿主应用的环境中直接访问子应用开发环境的服务
- 为确保热更新的正常使用,开发模式需要设置 publicPath, 参考 vue.config.js (opens new window), 其它框架类似。
TIP
更多高级特性参考:plugin-webpack
# 导出子应用的组件
子应用可以导出更细粒度的组件,导出的组件列表可以被宿主应用或者其他子应用使用。在组件共享、插件开发场景中有极大帮助。
以vue3
工程为例,其他工程相同
- 导出一个组件
import { createApp } from 'vue'
import App from './App.vue'
import PipelineApp from './PipelineApp.vue'
const app = createApp(App);
if (window.__JMODULE_HOST__) {
// 创建一个 app 类型的子应用
JModule.define('pipeline', {
mount(module, el, stats) { // 如果仅共享组件,则不需要 mount
if (stats.mountTimes === 0) {
app.mount(el);
}
},
exports: { // 导出一个组件
PipelineApp,
}
});
} else {
app.mount('#app')
}
- 在其他子应用中使用该组件
const getPipelineApp = JModule.require('pipeline.models.PipelineApp');
getPipelineApp.then((PipelineApp) => {
const pipelineAppIns = new PipelineApp({ appId: this.appId });
});
# 定义基准路由
举例:
// vue2
const router = new VueRouter({
mode: 'history',
base: 'blue', // blue 为 moduleKey,请自行替换
routes
})
// react
<Router basename={getBasename()}>
# 获取publicPath
# 获取方式
JModule.import('$module.meta')
# 结合webpack使用
__webpack_public_path__ = JModule.import('$module.meta')?.server
# Demo
# 宿主应用开发者
# 安装 @jmodle/client
npm install @jmodle/client --save
# 建立子应用定义规约
即根据自身需要,读取子应用 JModule.define 的配置参数进行进一步处理。即这里用什么字段,子应用才提供什么字段。
JModule.addHook('afterInit', (module, pkg) => {
// 实现子应用配置
if (module.type === 'app') {
return appAdapter(module, pkg);
}
// 实现基于路由的配置
if (module.type === 'module') {
return moduleAdapter(module, pkg);
}
return [module, pkg];
});
adapter实现具体参考:
moduleAdapter (opens new window)
可以根据需要,自行扩展其它 type 以及对应的 adapter。
# 注册子应用
const modules = JModule.registerModules([
{ key: 'app1', url: 'http://localhost:8080/index.js'},
{ key: 'app2', url: '...' }
]);
# 子应用预加载
modules.forEach(module => module.load('preload'));
# 子应用挂载
对于基于动态路由的子应用挂载,由宿主 router 处理,通常不需要额外处理,但可以通过路由钩子来实现细粒度控制。
对应通过生命周期方式挂载的完整子应用,需要一些特别处理,主要包括:
2.1 监听路由变化
2.2 按路由规则判断当前需要挂载的 module
2.3 加载模块:module.load()
2.4 bootstrapModule()
2.5 mountModule()
一段完整的示例可以参考:host-vue2 (opens new window)