微前端的模块加载器,主要功能为:
- 项目配置文件的加载
- 项目对外接口文件的加载(消息总线会用到,后续会提)
- 项目入口文件的加载
以上也是每一个单模块,不可缺少的三部分
配置文件
我们实践微前端的过程中,我们对每个模块项目,都有一个对外的配置文件.
是模块在注册到singe-spa时候所用到的信息.
{ "name": "name", //模块名称 "path": "/project", //模块url前缀 "prefix": "/module-prefix/", //模块文件路径前缀 "main": "/module-prefix/main.js", //模块渲染出口文件 "store": "/module-prefix/store.js",//模块对外接口 "base": true // 当模块被定性为baseApp的时候, // 不管url怎么变化,项目也是会被渲染的, // 使用场景为,模块职责主要为整个框架的布局或者一直被渲染,不会改变的部分 }
|
当我们的模块,有多种url前缀的时候,path也可以为数组形式
{ "path": ["/project-url-path1/","/project-url-path2/"], //项目url前缀 }
|
配置自动化
我们每个模块都有上面所描述的配置文件,当我们的项目多个模块的时候,我们需要把所有模块的配置文件聚合起来.
我这里也有写一个脚本.
micro-auto-config
使用方法:
npm install micro-auto-config -g
# 在项目根目录,用pm2启动该脚本,便可启动这个项目的配置自动化 pm2 start micro-auto-config
|
大概思路是:当模块部署,服务器检测到项目文件发生改变,便开始找出所有模块的配置文件,把他们合并到一起.
以数组包对象的形式输出一个总体的新配置文件 project.config.js
.
当我们一个模块配置有更新,部署到线上的时候,项目配置文件会自动更新.
模块加载器
这个文件直接引入到html中,也就是上一篇文章中的single-spa-config.js
升级版.
在加载模块的时候,我们使用SystemJS作为我们的模块加载工具.
"use strict"; import '../libs/es6-promise.auto.min' import * as singleSpa from 'single-spa'; import { registerApp } from './Register'
async function bootstrap() { // project.config.js 文件为所有模块的配置集合 let projectConfig = await SystemJS.import('/project.config.js' )
// 遍历,注册所有模块 projectConfig.projects.forEach( element => { registerApp({ name: element.name, main: element.main, url: element.prefix, store:element.store, base: element.base, path: element.path }); }); // 项目启动 singleSpa.start(); }
bootstrap()
|
Register.js
import '../libs/system' import '../libs/es6-promise.auto.min' 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 } 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, () => SystemJS.import(params.main), params.base ? (() => true) : pathPrefix(params));
}
//数组判断 用于判断是否有多个url前缀 function isArray(o){ return Object.prototype.toString.call(o)=='[object Array]'; }
|
未完待续 …
相关文章
前端单页应用微服务化解决方案1 - 思考
前端单页应用微服务化解决方案2 - Single-SPA
前端单页应用微服务化解决方案3 - 模块加载器
前端单页应用微服务化解决方案4 - 消息总线
前端单页应用微服务化解决方案5 - 路由分发
前端单页应用微服务化解决方案6 - 构建与部署
前端单页应用微服务化解决方案7 - 静态数据共享
Demo
前端微服务化 Micro Frontend Demo
微前端模块加载器
微前端Base App示例源码
微前端子项目示例源码