registerMicroApps配置子应用
start读取配置,拉取子应用并完成渲染
//全局变量
let _app = [];
//更好的获取全局变量_app
export const getApps = () => _app;
//app为传递过来的子应用数组
export const registerMicroApps = (app) => {
_app = app;
};
export const start = () => {
};
监控路由变化
import { getApps } from "./index.js"
import { fetchSource } from "./utils.js";
export const handleRouter = async () => {
const apps = getApps();
const app = apps.find(item => item.activeRule === window.location.pathname)
if (!app) {
return;
}
try {
const html = await fetchSource(app.entry);
const container = document.querySelector(app.container);
container.innerHTML = html;
} catch (e) {
console.log(e);
}
}
获取script并执行
完成getExternalScripts和execScripts函数
import { fetchSource } from "./utils.js";
export const importEntry = async (entry, options) => {
const content = await fetchSource(entry);
let template = document.createElement('div');
template.setAttribute('data-name', options.name);
template.innerHTML = content;
//数据存放缓存
const source = {
links: new Map(),
scripts: new Map()
}
const children = Array.from(template.children);
const scripts = children.filter(item => item.tagName === 'SCRIPT');
scripts.forEach(dom => {
const src = dom.getAttribute('src');
if (src) {
source.scripts.set(src, {
code: "", //具体js的代码内容,需要通过远程获取
isExternal:true,//是否是外链js
})
}
else if (dom.textContent) { //内链js
//随机名字,当做缓存键名
const randomName = Math.random().toString(36).substring(2,15);
source.scripts.set(randomName, {
code: dom.textContent,
isExternal:false,
})
}
});
console.log(source);
const assetPublicPath = options.name;
const getExternalScripts = () => {
//先将map中的内容转换成数组
const scriptEntries = Array.from(source.scripts.entries());
//声明远程获取的promise数组
const fetchScriptPromise = [];
for (let [url, info] of scriptEntries) {
console.log(url, info);
//这里的url可能是本地的相对地址
//由于我们有基座引用,如果是相对地址,就会到基座的下面去查找js文件
//所以这里需要将相对地址转换为子应用绝对地址
if (!url.includes('http') && info.isExternal) {
url = `${entry.endsWith('/') ? entry.substring(0, entry.length - 1) : entry}${url}`;
}
console.log(url)
//放入promise到数组中
fetchScriptPromise.push(info.code ? Promise.resolve(info.code) : fetchSource(url));
}
return Promise.all(fetchScriptPromise)
}
const execScripts = async () => {
const scriptEntries = Array.from(source.scripts.entries());
const scripts = await getExternalScripts();
scripts.forEach((code, i) => {
scriptEntries[i][1].code = code;
eval(code);
});
console.log(source);
}
}
部分代码
import { fetchSource } from './utils';
export const importEntry = async (entry,options) => {
//远程获取html字符串内容
const html = await fetchSource(entry);
let template = document.querySelector(`div[data-name=${options.name}]`);
console.log("template",template);
//如果没有template的div容器,就创建一个新的
if(!template){
template = document.createElement('div');
template.setAttribute('data-name',options.name);
template.innerHTML = html;
}
//设置缓存
const source = {
scripts: new Map()
}
//template.children 是一个伪数组
const children = Array.from(template.children);
//获取所有的script标签
const scripts = children.filter(item => item.tagName === 'SCRIPT');
scripts.forEach(dom => {
const src = dom.getAttribute('src');
if(src){
source.scripts.set(src,{
code:'', //如果是外链的script,还需要通过远程获取
isExternal:true //是否是外链js
});
}
else if(dom.textContent){
//内链js
//随机给一个map的键名
const randomName = Math.random().toString(36).substring(2,15);
source.scripts.set(randomName,{
code:dom.textContent,
isExternal:false
})
}
})
const getExternalScripts = () => {
//获取缓存中存放的所有外链script地址
const scriptEntries = Array.from(source.scripts.entries());
const fetchScriptPromise = [];
for(let [url,info] of scriptEntries){
console.log(url,info);
//这里的url可能是本地的绝对地址 /开头,也可能是远程的绝对地址 http开头
//如果是本地的绝对地址,需要拼接上子应用的地址
//因为/开头的话,在基座应用中,加上的就是基座应用的域名地址
if(!url.includes('http') && info.isExternal){
url = `${entry.endsWith('/') ? entry.substring(0,entry.length-1) : entry}${url}`;
console.log("----",url)
}
//info.code如果有,表明是内链的js
fetchScriptPromise.push(info.code ? Promise.resolve(info.code) : fetchSource(url));
}
console.log(fetchScriptPromise);
return Promise.all(fetchScriptPromise);
};
const execScripts = async () => {
//获取缓存中存放的所有外链script地址
const scriptEntries = Array.from(source.scripts.entries());
const scripts = await getExternalScripts();
scripts.forEach((code,i) => {
scriptEntries[i][1].code = code;
eval(code);
})
};
return {
template,
getExternalScripts,
execScripts
}
}
页面效果