6.模块加载器
这里的模块加载器,其实主要就是通过汇集每个应用的配置文件,批量注册应用
配置文件
在每个应用下新建配置文件,比如在src/vue下新建config.js
export default {
"name": "vue", //模块名称
"path": "/vue-project", //模块url前缀
"prefix": "/vue", //模块文件路径前缀
"main": "vue/vue.app.js", //模块渲染出口文件
"store": "./src/vue/store.js",//模块对外接口
"base": false
// 当模块被定性为baseApp的时候,
// 不管url怎么变化,项目也是会被渲染的,
// 使用场景为,模块职责主要为整个框架的布局或者一直被渲染,不会改变的部分
}
聚合配置文件
将所有应用的配置文件汇总成一个数组
- 在根目录下建project.config.js
import reactConfig from './src/react/config.js';
import vueConfig from './src/vue/config.js';
export default [
reactConfig,
vueConfig,
]
改造single-spa.config.js
我们原先写的single-spa.config.js的目的就是用于注册一个个应用,然后启动。那么由于已经拿到了所有应用的配置,所以可以通过改造,批量注册(其实就是数组遍历,low爆了)。
require('babel-polyfill')
import * as singleSpa from 'single-spa';
// 导入所有模块的配置集合
import projectConfig from './project.config.js';
import { registerApp } from './Register';
async function bootstrap(){
// 批量注册:对所有模块依次注册
projectConfig.forEach(config => {
registerApp({
name: config.name,
main: config.main,
url: config.prefix,
store: config.store,
base: config.base,
path: config.path,
})
})
singleSpa.start();
}
// 初始化,批量注册并启动
bootstrap();
我们可以看出,该文件的关键就是bootstrap函数,而该函数就是遍历总配置的数组,将每个应用的配置注入到registerApp函数中。那么这个registerApp函数用来干嘛的呢?显然,咱们这个文件的目的尚未实现——注册应用。所以,我们registerApp的代码主要就是注册应用。
- 创建注册器文件Register.js
在这里,由于我们需要根据路由来判断加载哪个应用,所以需要考虑到路由的两种模式,hash和history模式。
import * as singleSpa from 'single-spa';
// hash 模式,项目路由用的是hash模式会用到该函数
export function hashPrefix(app) {
return function (location) {
let isShow = false
//如果该应用 有多个需要匹配的路劲
if(isArray(app.path)){
app.path.forEach(path => {
if(location.hash.startsWith(`#${path}`)){
isShow = true
}
});
}
// 普通情况
else if(location.hash.startsWith(`#${app.path || app.url}`)){
isShow = true
}
console.log('hashPrefix', isShow)
return isShow;
}
}
// pushState 模式
export function pathPrefix(app) {
return function (location) {
let isShow = false
//如果该模块 有多个需要匹配的路径
if(isArray(app.path)){
app.path.forEach(path => {
if(location.pathname.indexOf(`${path}`) === 0){
isShow = true
}
});
}
// 普通情况
else if(location.pathname.indexOf(`${app.path || app.url}`) === 0){
isShow = true
}
return isShow;
}
}
// 应用注册
export async function registerApp(params) {
singleSpa.registerApplication(params.name, () => {
return import(`./src/${params.main}`)
}, params.base ? (() => true) : pathPrefix(params));
}
//数组判断 用于判断是否有多个url前缀
function isArray(o){
return Object.prototype.toString.call(o)=='[object Array]';
}
至此,模块改造器就完成了。
启动
- 此时,你启动npm start命令,就可以访问了
# 地址为/react时,只加载react应用
http://localhost:8080/react-project
# 地址为/vue时,只加载vue应用
http://localhost:8080/vue-project
# 地址为非/react-project或非/vue-project时,vue和react都不加载
http://localhost:8080/ (都不展示)
- 在这里,需要注意的是:
- 现在访问/react-project和/vue-project,不再是/react和/vue,因为我们在配置文件的path中规定了访问前缀
- 现在访问除了/react-project和/vue-project之外的都不显示,不再像以前一样,访问/都显示,这是因为registerApplication第三个参数的函数中做了判断和限定。