基于Create React App的浏览器扩展:getBackgroundPage()无法访问背景脚本变量求助
我来帮你拆解下为啥getBackgroundPage()拿不到背景脚本里的变量和函数,以及怎么解决这个问题~
核心原因:Webpack的模块作用域封装
你用Create React App开发,它底层是Webpack打包代码的。默认情况下,Webpack会把每个脚本都包裹在模块作用域里——也就是说你在background_3.js里定义的var test和function foo,只会存在于这个模块的局部作用域中,不会自动挂载到背景页的全局window对象上。而browser.runtime.getBackgroundPage()返回的就是背景页的window,自然找不到这些未暴露的变量和函数。
另外,如果你的manifest里声明了多个背景脚本,浏览器确实会把它们加载到同一个背景页的window环境里,但每个脚本如果是被Webpack处理过的模块,各自的变量依然是隔离的,除非你主动把它们挂载到全局。
解决方案:显式暴露变量/函数到全局window
最简单直接的办法,就是把需要在新标签页访问的变量和函数,手动挂载到背景页的window对象上:
修改背景脚本background_3.js
// 把变量挂载到window window.test = []; for (let i = 0; i < 10; ++i) { window.test.push(i); } // 把函数挂载到window window.foo = function() { console.log("foo"); };
这样当你在新标签页调用browser.runtime.getBackgroundPage()拿到page对象(也就是背景页的window)时,就能正常访问page.test和调用page.foo()了。
可选方案:调整Webpack配置(进阶)
如果你不想手动挂载全局变量,可以修改Webpack的配置,让背景脚本打包后直接把内容暴露到window。不过Create React App默认不让直接改Webpack配置,你需要:
- 执行
npm run eject(不可逆),或者用react-app-rewired这类工具来覆盖配置 - 在Webpack的output配置里,设置
libraryTarget: 'window',这样整个模块的导出会自动挂载到window上
不过这个方案相对复杂,除非你有大量变量/函数需要暴露,否则优先用上面的手动挂载方法更省心。
是否需要改用消息API?
不一定非要换!getBackgroundPage()在简单的场景下(比如直接访问背景页的变量/同步调用函数)其实更高效。但如果你的通信场景比较复杂:
- 需要跨不同上下文(比如内容脚本和背景页)
- 涉及异步操作较多
- 不想暴露全局变量担心污染环境
那改用消息API(browser.runtime.sendMessage/browser.runtime.onMessage)会更优雅,也更符合浏览器扩展的最佳实践。
内容的提问来源于stack exchange,提问作者user8302493

