如何修复Chrome扩展“Uncaught Reference Error: document is not defined”错误
问题解决:Chrome扩展后台脚本访问document报错
错误原因
你的background.js是作为Service Worker运行的(Manifest V3的设定),它完全独立于网页环境,没有DOM对象(document、location这些都不存在),所以直接写if (document !== undefined)会直接抛出ReferenceError——因为document这个变量根本没被定义过,连判断都做不了。
而且你把DOM操作逻辑都写在后台脚本里也是错误的,后台脚本无权直接操作网页DOM,必须通过Content Script注入到目标页面执行。
修正方案
1. 重构background.js
后台只负责处理图标点击、状态切换,触发时向当前标签页注入脚本执行DOM操作:
chrome.runtime.onInstalled.addListener(() => { chrome.action.setBadgeText({ text: "OFF", }); }); chrome.action.onClicked.addListener(async (tab) => { // 检查当前标签页是否是http/https网站 if (!tab.url.startsWith('http')) return; const prevState = await chrome.action.getBadgeText({ tabId: tab.id }); const nextState = prevState === 'ON' ? 'OFF' : 'ON'; await chrome.action.setBadgeText({ tabId: tab.id, text: nextState, }); if (nextState === "ON") { // 注入处理单词高亮的脚本到当前页面 await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: highlightWords, args: [["dog", "cats"]] // 传递要查找的单词列表 }); } else if (nextState === "OFF") { // 重新加载页面恢复原状 await chrome.tabs.reload(tab.id); } }); // 要注入到页面的函数(会在页面环境执行,拥有DOM权限) function highlightWords(wordList) { const elements = document.querySelectorAll('body *:not(script):not(noscript):not(style)'); elements.forEach(el => { // 只处理文本节点的父元素,避免破坏标签结构 if (el.childNodes.length === 1 && el.childNodes[0].nodeType === Node.TEXT_NODE) { let text = el.textContent; wordList.forEach(word => { const regex = new RegExp(`\\b${word}\\b`, 'gi'); text = text.replace(regex, '***$&***'); // 用***包裹高亮,你可以改成样式高亮 }); el.textContent = text; } }); }
2. 保留原manifest.json(无需修改)
你的manifest已经配置了activeTab和scripting权限,刚好支持注入脚本的操作,不需要额外改动。
关键改动说明
- 移除了后台脚本中所有DOM相关代码,把DOM操作逻辑放到
highlightWords函数中,通过chrome.scripting.executeScript注入到页面执行。 - 用
chrome.tabs.reload替代原来的location.reload,后台脚本无法直接访问页面的location,必须通过tabs API操作。 - 优化了单词匹配逻辑:只处理纯文本节点,避免替换标签属性里的内容,同时用正则边界
\b避免部分匹配(比如避免把"doggy"里的"dog"也替换)。
内容的提问来源于stack exchange,提问作者thelovelightliveventure
相关产品推荐
相关产品推荐

