在写这个之前,我们先说下fetch
fetch
什么是fetch: 在msdn上是这样说的,提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
这种功能以前是使用 XMLHttpRequest 实现的。Fetch 提供了一个更理想的替代方案,可以很容易地被其他技术使用,例如 Service Workers。Fetch 还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。
fetch 与 jQuery.ajax()
当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject, 即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
fetch() 可以不会接受跨域 cookies;你也可以不能使用 fetch() 建立起跨域会话。其他网站的 Set-Cookie 头部字段将会被无视。
fetch 不会发送 cookies。除非你使用了credentials 的初始化选项。(自 2017 年 8 月 25 日以后,默认的 credentials 政策变更为 same-origin。Firefox 也在 61.0b13 版本中进行了修改)
fetch简单使用
fetch('http://127.0.0.1:5500/demo1.html')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
在这里我为什么说fetch呢?因为接下要使用这个。因为我们都知道,微前端的出现就是为了解决各个项目之间的联系,也就是把各个项目合并到一个项目中,减少开发的时间。所以每个项目都有相应的地址或者入口,比我们公司都是vue的当页面应用,所以整合起来非常简单,我们通过fetch 请求入口地址拿到html,经过处理插入一个项目中就可以实现。如下:
我的一个项目地址是: http://192.168.1.140:7001/
fetch('http://192.168.1.140:7001/')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
console.log(myJson);
});
然后通过解析dom,分别请求js和style
scripts
const scripts = dom.querySelectorAll('script');
const paromiseArr =
scripts &&
Array.from(scripts).map((item) => {
if (item.src) {
const url = window.location.protocol + '//' + window.location.host;
const path = item.src.replace(url, '');
const needEntryPath = !/(http|https):\/\/([\w.]+\/?)\S*/.test(path);
return fetch(`${needEntryPath ? 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);
});
}
style
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;
const path = item.href.replace(url, '');
const needEntryPath = !/(http|https):\/\/([\w.]+\/?)\S*/.test(path);
return fetch(`${needEntryPath ? 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);
});
}
完整的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo</title>
</head>
<body>
<div>
<!-- <custom-element>sadasdasdasdas</custom-element> -->
<div id="main-content"></div>
</div>
<script> fetch('http://192.168.1.140:7001/').then(function(response) { return response.text() }).then(async function (text) { const mainApp = document.querySelector('#main-content'); let tempNode = document.createElement('div') tempNode.innerHTML = text mainApp.appendChild(tempNode) return { tempNode, mainApp } }).then(async function ({ tempNode, mainApp}) { await loadScripts() await loadStyle() }) async function loadScripts (dom, mainApp) { const scripts = tempNode.querySelectorAll('script'); const paromiseArr = scripts && Array.from(scripts).map((item) => { if (item.src) { const url = window.location.protocol + '//' + window.location.host; const path = item.src.replace(url, ''); const needEntryPath = !/(http|https):\/\/([\w.]+\/?)\S*/.test(path); return fetch(`${needEntryPath ? 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 mainApp.appendChild(script) }) } } async function loadStyle (dom, mainApp) { const scripts = dom.querySelectorAll('script'); const paromiseArr = scripts && Array.from(scripts).map((item) => { if (item.src) { const url = window.location.protocol + '//' + window.location.host; const path = item.src.replace(url, ''); const needEntryPath = !/(http|https):\/\/([\w.]+\/?)\S*/.test(path); return fetch(`${needEntryPath ? 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; mainApp.appendChild(script); }); } } </script>
</body>
</html>
初步思路是这样的实现的的原理;
更完整的请看这篇的实现