let _apps = [];
let prevRoute = '';
let nextRoute = window.location.pathname;
export const registerMicroApps = (apps) => {
_apps = apps;
};
export const importHTML = async (url) => {
const html = await fetch(url).then(res => res.text());
const template = document.createElement('div');
template.innerHTML = html;
const scripts = template.querySelectorAll('script');
const getExternalScripts = () => {
return Promise.all(Array.from(scripts).map(script => {
const src = script.getAttribute('src');
if (!src) {
return Promise.resolve(script.innerHTML);
} else {
return fetch(src.startsWith('http') ? src : `${url}${src}`).then(res => res.text());
}
}))
}
const execScripts = async () => {
const scripts = await getExternalScripts();
const module = { exports: {} }
const exports = module.exports;
scripts.forEach(code => eval(code));
return module.exports;
}
return {
template,
getExternalScripts,
execScripts,
}
}
const handleRouter = async () => {
const prevApp = _apps.find(item => prevRoute.startsWith(item.activeRule));
const app = _apps.find(item => window.location.pathname.startsWith(item.activeRule));
if (prevApp) {
await unmount(prevApp)
}
if (!app) return;
const { template, execScripts } = await importHTML(app.entry);
const container = document.querySelector(app.container);
container.appendChild(template);
window.__POWERED_BY_QIANKUN__ = true;
window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__ = app.entry + '/';
const appExports = await execScripts();
app.bootstrap = appExports.bootstrap;
app.mount = appExports.mount;
app.unmount = appExports.unmount;
await bootstrap(app);
await mount(app);
}
export const start = () => {
window.addEventListener("popstate", () => {
prevRoute = nextRoute;
nextRoute = window.location.pathname;
handleRouter();
});
const rawPushState = window.history.pushState;
window.history.pushState = (...args) => {
prevRoute = window.location.pathname;
rawPushState.apply(window.history, args);
nextRoute = window.location.pathname;
handleRouter();
}
const rawReplaceState = window.history.replaceState;
window.history.replaceState = (...args) => {
prevRoute = window.location.pathname;
rawReplaceState.apply(window.history, args);
nextRoute = window.location.pathname;
handleRouter();
}
handleRouter();
};
async function bootstrap(app) {
app.bootstrap && (await app.bootstrap())
}
async function mount(app) {
app.mount && (await app.mount({
container: document.querySelector(app.container)
}))
}
async function unmount(app) {
app.unmount && (await app.unmount({
container: document.querySelector(app.container)
}))
}
`