chunchao
源碼開源,僅僅爲了讓你們學習微前端的工做模式而已,實際項目中,咱們有使用Paas模式,web components,git submodule等模式均可以實現微前端,固然業內確定有獨特的、優於這些模式的微前端實現export async function loadApp() { const shouldMountApp = Apps.filter(shouldBeActive); console.log(shouldMountApp, 'shouldMountApp'); fetch(shouldMountApp[0].entry) .then(function (response) { return response.text(); }) .then(function (text) { const dom = document.createElement('div'); dom.innerHTML = text; const subapp = document.querySelector('#subApp-content'); subapp && subapp.appendChild(dom); }); }
dom
節點,渲染到基座的對應子應用節點中script
、style
標籤❝樣式隔離、沙箱隔離並非難題,這裏不着重實現,能夠參考shadow dom,qiankun的proxy隔離代理window實現html
❞前端
fetch
去加載·
script、style`標籤,而後用key-value形式緩存在一個對象中(方便緩存第二次直接獲取),他們的fetch還能夠用閉包傳入或者使用默認的fetch,這裏不作過多源碼解析`<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>subapp1</title> </head> <body> <div>subapp1</div> </body> <script src="/index.js"></script> <script> alert('subapp1') </script> </html>
script
標籤,須要加載,根據加載方式,分爲html內部的和經過script標籤引入的<script src="/index.js"></script> <script> alert('subapp1') </script>
`export async function loadApp() { const shouldMountApp = Apps.filter(shouldBeActive); const App = shouldMountApp.pop(); }); `
script src="/index.js"
,可是讀取script標籤的src屬性,會自動+上主應用的前綴,因此要考慮下如何處理const url = window.location.protocol+"//"+window.location.host `
const res = await Promise.all(paromiseArr); console.log(res, 'res'); if (res && res.length > 0) { res.forEach((item) => { const script = document.createElement('script'); script.innerText = item; subapp.appendChild(script); }); }
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); }); } }); }
`subapp.appendChild(dom); handleScripts(entryPath,subapp,dom);`
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 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 subapp = document.querySelector('#subApp-content'); subapp.appendChild(dom); handleScripts(entryPath, subapp, dom); }); } `
`<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>subapp1</title> <style> body { color: red; } </style> </head> <body> <div>subapp1</div> </body> <script src="/index.js"></script> <script> alert('subapp1') </script> </html> `
handleScripts(entryPath, subapp, dom); handleStyles(entryPath, subapp, dom);
`` 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); }); } } ``
❝這裏能夠作個promise化,若是加載失敗能夠報個警告控制檯,封裝框架大都須要這個,不然沒法debug.我這裏作乞丐版,目前就不作那麼正規了,設計框架原則你們不能忘記哈webpack
❞git
https://github.com/JinJieTan/chunchao
,記得給個star
哦若是你對性能優化有很深的研究,能夠跟我一塊兒交流交流,今天這裏寫得比較淺,可是大部分人都夠用,以前問個人朋友,我讓它寫了一個定時器定時消費隊列,最後也能用。哈哈github
另外歡迎收藏個人資料網站:前端生活社區:https://qianduan.life
,感受對你有幫助,能夠右下角點個在看
,關注一波公衆號:[前端巔峯
]web