45

实现微前端的十种方式 【第二种】

 3 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzI2NTk2NzUxNg%3D%3D&%3Bmid=2247487404&%3Bidx=1&%3Bsn=ffe076ae2b180679284ed62dceb4ae8a
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

实现微前端的十种方式 【二】

目前主流的微前端实现方式(基座加载式)

  • 以基座为入口,配置不同的子应用入口地址,达到实现微前端的效果

  • chunchao
    qiankun
    chunchao
    
  • 微前端基座模式配置

BzeQ733.png!web
  • 加载示意图

3Y3ye26.png!web

如何实现基座模式加载子应用?

  • 劫持前端路由,重写 hashchangepopstate 事件
const HIJACK_EVENTS_NAME = /^(hashchange|popstate)$/i;
const EVENTS_POOL = {
hashchange: [],
popstate: [],
};

window.addEventListener('hashchange', loadApps);
window.addEventListener('popstate', loadApps);

const originalAddEventListener = window.addEventListener;
const originalRemoveEventListener = window.removeEventListener;
window.addEventListener = function (eventName, handler) {
if (
eventName &&
HIJACK_EVENTS_NAME.test(eventName) &&
typeof handler === 'function'
) {
EVENTS_POOL[eventName].indexOf(handler) === -1 &&
EVENTS_POOL[eventName].push(handler);
}
return originalAddEventListener.apply(this, arguments);
};
  • 根据不同的入口,去拉取子应用的 jscss 等资源 RvqQN3V.png!web
  • 注册子应用后存入队列中


/**
*
* @param {string} entry
* @param {string} function
*/
const Apps = [] //子应用队列
function registryApp(entry,activeRule) {
Apps.push({
entry,
activeRule
})
}
  • 注册完了之后,就要找到需要加载的app,并且拉取资源

export async function loadApp() {
const shouldMountApp = Apps.filter(shouldBeActive);
const App = shouldMountApp.pop();
fetch(App.entry)
.then(function (response) {
return response.text();
})
.then(async function (text) {
const dom = document.createElement('div');
dom.innerHTML = text;
const entryPath = App.entry;
const scripts = dom.querySelectorAll('script');
const subapp = document.querySelector('#subApp-content');
const paromiseArr =
scripts &&
Array.from(scripts).map((item) => {
if (item.src) {
const url = window.location.protocol + '//' + window.location.host;
return fetch(`${entryPath}/${item.src}`.replace(url, '')).then(
function (response) {
return response.text();
}
);
} else {
return Promise.resolve(item.textContent);
}
});
subapp.appendChild(dom);
const res = await Promise.all(paromiseArr);
if (res && res.length > 0) {
res.forEach((item) => {
const script = document.createElement('script');
script.innerText = item;
subapp.appendChild(script);
});
}
});
}
  • shouldBeActive根据传入的规则去判断是否需要此时挂载:

export function shouldBeActive(app){
return app.activeRule(window.location)
}
  • 处理脚本文件

export async function handleScripts(entryPath,subapp,dom) {
const scripts = dom.querySelectorAll('script');
const paromiseArr =
scripts &&
Array.from(scripts).map((item) => {
if (item.src) {
const url = window.location.protocol + '//' + window.location.host;
return fetch(`${entryPath}/${item.src}`.replace(url, '')).then(
function (response) {
return response.text();
}
);
} else {
return Promise.resolve(item.textContent);
}
});
const res = await Promise.all(paromiseArr);
if (res && res.length > 0) {
res.forEach((item) => {
const script = document.createElement('script');
script.innerText = item;
subapp.appendChild(script);
});
}
}
  • 处理样式文件


export async function handleStyles(entryPath, subapp, dom) {
const arr = [];
const styles = dom.querySelectorAll('style');
const links = Array.from(dom.querySelectorAll('link')).filter(
(item) => item.rel === 'stylesheet'
);
const realArr = arr.concat(styles,links)
const paromiseArr =
arr &&
Array.from(realArr).map((item) => {
if (item.rel) {
const url = window.location.protocol + '//' + window.location.host;
return fetch(`${entryPath}/${item.href}`.replace(url, '')).then(
function (response) {
return response.text();
}
);
} else {
return Promise.resolve(item.textContent);
}
});
const res = await Promise.all(paromiseArr);
if (res && res.length > 0) {
res.forEach((item) => {
const style = document.createElement('style');
style.innerHTML = item;
subapp.appendChild(style);
});
}
}
  • 此时,我们已经可以加载不同的子应用了。

最后

  • 认真收藏这个系列吧,记得点个关注和在看,相信你能收获很多很多~

  • Peter
    IM
    APP
    
  • https://qianduan.life
    在看
    关注
    前端巅峰
    

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK