總體架構設計
項目地址【部分代碼】
注意點:git
1.xhr 「重寫」github
import { dispatch } from "../event"; import { AJAX_RESPONSE_TIME, AJAX_STATUS_ERROR } from "../listen/type"; const xhrMdifiy = ( options = { witheList: [], } ) => { // 全局變量 const win = window; // 標準ajax const XMLHttpRequest = win.XMLHttpRequest; // fetch const fetch = win.fetch; //out XML const OutXMLHttpRequest = function () { const startTime = Date.now(); const xhr = new XMLHttpRequest(); const self = this; const readystatechangeEvent = []; const onerrorEvent = []; let body = null; const rHeaders = []; let type = ''; const catchNormalRequestStatus = function (e) { const { currentTarget } = e; const { response, responseURL } = currentTarget; const endTime = Date.now(); if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.status === 200) { let diffTime = endTime - startTime; dispatch(AJAX_RESPONSE_TIME, diffTime); } else { const requestHeaders = rHeaders.reduce((p, q) => { return { ...p, [q[0]]: q[1], }; }, {}); if (typeof body === "string") { body = body; } if (body instanceof FormData) { const bCopy = {}; for (let pair of formData.entries()) { if (bCopy[1] instanceof Blob) { bCopy[pair[0]] = { fileName: bCopy[1].fileName, size: bCopy[1].size, }; } else { bCopy[pair[0]] = pair[1]; } } } if (body instanceof Blob) { const bCopy = {}; bCopy = { fileName: body.fileName, size: body.size, }; } if (body instanceof Object) { body = JSON.stringify(body); } const postData = { type, body, response, responseURL, requestHeaders, } console.log(postData) dispatch(AJAX_STATUS_ERROR, postData); } } }; // readystatechangeEvent.push(catchNormalRequestStatus); // 代理 xhr 對象 for (let key in xhr) { if (["setRequestHeader", "send", 'open'].includes(key)) { continue; } Object.defineProperty(self, key, { get() { if (typeof xhr[key] === "function") { return xhr[key].bind(xhr); } return xhr[key]; }, set(arg) { switch (key) { case "onreadystatechange": { const fn = arg; fn && readystatechangeEvent.push(fn); break; } default: { xhr[key] = arg; } } }, }); } // 重寫 爲了獲取 請求類型 self.open = function (...arg) { type = arg[0] xhr.open.apply(xhr, arg) } // 重寫爲了獲取 發送數據 self.send = function (data) { body = data; xhr.send(data); }; self.setRequestHeader = function (...arg) { rHeaders.push(arg); xhr.setRequestHeader(...arg); }; // 檢查狀態變動 【默認注入一個監聽事件】 xhr.onreadystatechange = function (e) { readystatechangeEvent.forEach((fn) => { if (typeof fn === "function") { fn.call(xhr, e); } }); }; return self; }; win.XMLHttpRequest = OutXMLHttpRequest; }; export default xhrMdifiy;
2.資源加載 及 代碼報錯web
import { LOAD_SOURCE_ERROR, SCRIPT_EXECUTE_ERROR } from "../listen/type"; import { dispatch, on } from "../event"; import { event } from "@l6zt/cutils"; const win = window; const doc = window.document; /* 處理文件資源加載報錯 標籤中必須有【crossorigin="anonymous"】 <script src="xx" crossorigin="anonymous" ></script> 】 */ event.on(win, 'error', (e) => { const { message, filename, lineno, colno, srcElement } = e; if (filename) { const payload = { message, filename, lineno, colno, } console.log(payload) dispatch(SCRIPT_EXECUTE_ERROR, payload); } }); // 觀察資源加載狀況 【觀察 docment 」媒體元素「 插入狀況】 const observer = new MutationObserver((mutationsList, observer) => { mutationsList.forEach((mutation) => { const { type, addedNodes } = mutation; if (type === "childList") { addedNodes.forEach((el) => { if ( [HTMLScriptElement, HTMLImageElement,HTMLVideoElement, HTMLAudioElement, Image ].find((C) => el instanceof C ) ) { event.on(el, 'error', (e) => { const { target } = e; const payload = { type: target.localName, src: target.getAttribute('src') || target.getAttribute('href') } console.log(payload) dispatch(LOAD_SOURCE_ERROR, payload) }) } }); } }); }); observer.observe(doc, { attributes: true, childList: true, subtree: true });
3.性能監控 【例子】ajax
const win = window win.addEventListener('load', function() { const perfData = window.performance.timing; const pageLoadTime = perfData.loadEventEnd - perfData.navigationStart; const connectTime = perfData.responseEnd - perfData.requestStart; const renderTime = perfData.domComplete - perfData.domLoading; });