Chrome扩展问题:未刷新时GitHub拉取请求标签页无法执行内容脚本
这个问题的核心原因是GitHub是单页应用(SPA):切换标签页(比如从代码到拉取请求)时,页面并没有重新加载,只是通过history.pushState更新了URL和DOM内容,而Chrome扩展的默认Content Script注入逻辑只会在页面初始加载时触发一次,所以切换标签后不会重新执行content.js。
下面给你几个可行的解决方案,按推荐程度排序:
方案1:用Background Script监听历史状态变化(最可靠)
通过Chrome的webNavigationAPI监听页面的历史状态更新,当检测到URL切换到拉取请求页面时,主动注入并执行你的content.js逻辑。
步骤1:更新manifest.json
需要添加webNavigation权限和对应的主机权限:
{ "manifest_version": 3, "name": "你的扩展名称", "version": "1.0", "permissions": ["webNavigation", "scripting"], "host_permissions": ["*://github.com/*"], "background": { "service_worker": "background.js" } }
步骤2:编写background.js
监听onHistoryStateUpdated事件,判断当前URL是否匹配拉取请求页面,然后注入脚本:
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => { // 检查当前URL是否是拉取请求页面 if (details.url.includes('/pulls')) { // 注入并执行content.js的逻辑 chrome.scripting.executeScript({ target: { tabId: details.tabId }, files: ['content.js'] }); } }, { url: [{ hostSuffix: 'github.com', pathContains: '/pulls' }] });
注意:如果你的
content.js里有重复执行的问题(比如多次注入),可以在脚本里加一个标记,比如检查是否已经初始化过:if (window.hasRunPullsScript) return; window.hasRunPullsScript = true; // 你的核心逻辑代码
方案2:在Content Script里监听DOM变化(轻量)
GitHub切换标签时会更新页面的主内容容器(通常是#js-repo-pjax-container),可以用MutationObserver监听这个容器的变化,当内容更新时检查当前是否在拉取请求页面,然后执行逻辑。
修改你的content.js:
function initPullsLogic() { // 这里写你原本要在拉取请求页面执行的逻辑 console.log('执行拉取请求页面的脚本'); } // 初始加载时先检查一次 if (window.location.pathname.includes('/pulls')) { initPullsLogic(); } // 监听主容器的DOM变化 const observer = new MutationObserver((mutations) => { // 每次DOM变化后,检查当前URL是否是拉取请求页面 if (window.location.pathname.includes('/pulls')) { initPullsLogic(); } }); // 监听主内容容器的变化 observer.observe(document.querySelector('#js-repo-pjax-container'), { childList: true, subtree: true });
这个方案不需要Background Script,适合逻辑比较简单的场景,缺点是需要准确找到GitHub的主容器(如果GitHub更新DOM结构可能会失效)。
方案3:监听GitHub的自定义PJAX事件(最贴合GitHub的机制)
GitHub用PJAX做页面导航,会触发pjax:complete自定义事件,你可以直接监听这个事件,然后检查页面是否是拉取请求页面:
修改content.js:
function initPullsLogic() { // 你的核心逻辑 } // 初始加载 if (window.location.pathname.includes('/pulls')) { initPullsLogic(); } // 监听PJAX完成事件 document.addEventListener('pjax:complete', () => { if (window.location.pathname.includes('/pulls')) { initPullsLogic(); } });
这个方案最贴合GitHub的导航机制,但依赖GitHub的内部事件,如果未来GitHub修改了PJAX的事件名称,可能会失效。
内容的提问来源于stack exchange,提问作者yakkisyou

