如何检测网页中各请求对应的加载来源脚本?
获取请求的发起来源信息
你提到的Performance API(包括performance.getEntries())确实无法直接提供请求的发起者关联信息,但可以通过以下几种方法实现类似Speedcurve中“loaded by”的功能:
方法一:重写XHR/Fetch方法追踪调用栈
通过拦截页面中所有fetch和XMLHttpRequest的调用,记录请求发起时的调用栈,后续将调用栈信息与Performance API获取的资源条目关联,就能定位到发起请求的脚本。
代码示例:
// 初始化存储请求来源的对象 window.requestSources = window.requestSources || {}; // 重写fetch方法 const originalFetch = window.fetch; window.fetch = function(...args) { const requestUrl = typeof args[0] === 'string' ? args[0] : args[0].url; // 记录调用栈 window.requestSources[requestUrl] = new Error().stack; return originalFetch.apply(this, args); }; // 重写XMLHttpRequest方法 const originalXHR = XMLHttpRequest; XMLHttpRequest = function() { const xhr = new originalXHR(); const originalOpen = xhr.open; xhr.open = function(method, url) { window.requestSources[url] = new Error().stack; return originalOpen.apply(this, arguments); }; return xhr; }; // 页面加载完成后关联Performance条目与来源信息 setTimeout(() => { performance.getEntriesByType('resource').forEach(entry => { const sourceStack = window.requestSources[entry.name]; console.log(`请求: ${entry.name}`); console.log(`发起来源调用栈:\n${sourceStack || '无法追踪(可能为页面初始加载资源)'}`); }); }, 5000);
注意:需要在页面加载早期注入这段代码(比如通过Tampermonkey脚本或浏览器扩展),否则会漏掉页面初始阶段的请求。
方法二:使用Chrome DevTools Protocol(CDP)
如果是做自动化性能分析(类似WebPageTest/Speedcurve的场景),可以通过CDP的Network.requestWillBeSent事件获取请求的initiator信息,其中包含发起请求的脚本URL、行号甚至类型(比如script、img、fetch等)。
以Puppeteer为例的代码示例:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); page.on('request', request => { const initiator = request.initiator(); let sourceInfo = '页面本身'; if (initiator.type === 'script' && initiator.url) { sourceInfo = `${initiator.type} - ${initiator.url}:${initiator.lineNumber}`; } else if (initiator.type !== 'other') { sourceInfo = initiator.type; } console.log(`请求URL: ${request.url()}`); console.log(`Loaded by: ${sourceInfo}`); request.continue(); }); await page.goto('目标页面URL'); await browser.close(); })();
这种方法能直接拿到和Speedcurve一致的“loaded by”信息,准确性最高。
方法三:MutationObserver监控动态插入的资源
对于通过DOM动态插入的脚本、图片等资源,可以用MutationObserver监控DOM变化,记录插入这些资源的脚本上下文:
window.scriptSources = window.scriptSources || {}; const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if ((node.tagName === 'SCRIPT' || node.tagName === 'IMG') && node.src) { window.scriptSources[node.src] = new Error().stack; } }); }); }); observer.observe(document, { childList: true, subtree: true });
这种方法仅适用于追踪通过DOM添加的资源,无法覆盖XHR/Fetch发起的请求。
内容的提问来源于stack exchange,提问作者user21863572
相关产品推荐
相关产品推荐

