45
实现微前端的十种方式 【第二种】
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源码
-
简单的文章,通俗易懂,感觉不错记得点个
在看
和关注
哦 -
之前的原创以及好文推荐:
-
微前端框架chunchao(春潮)开源啦 基于 qiankun 的微前端最佳实践(万字长文) - 从 0 到 1 篇 基于 qiankun 的微前端最佳实践(万字长文) - 从 0 到 1 篇
目前主流的微前端实现方式(基座加载式)
-
以基座为入口,配置不同的子应用入口地址,达到实现微前端的效果
-
chunchao qiankun chunchao
-
微前端基座模式配置
-
加载示意图
如何实现基座模式加载子应用?
-
劫持前端路由,重写
hashchange
和popstate
事件
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);
};
-
根据不同的入口,去拉取子应用的
js
、css
等资源 -
注册子应用后存入队列中
/**
*
* @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 在看 关注 前端巅峰
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK