Chrome扩展Manifest V3迁移报XMLHttpRequest非构造函数错误
问题:Manifest V3扩展迁移时抛出
global.XMLHttpRequest is not a constructor错误 问题背景
此前开发了Manifest V2版本Chrome扩展,目前正在迁移至Manifest V3版本。
已按照V3规范修改manifest配置文件,但在chrome://extensions页面加载安装扩展时出现如下报错:
自身业务代码中从未使用过var xhr = new global.XMLHttpRequest()这段代码,无法定位调用来源,需要协助排查解决。
该扩展基于AngularJS开发,通过脚本生成build目录,使用gulp和browserify完成代码打包,初步判断报错来自引入的依赖库,但无法确定具体来源。
相关配置
package.json中devDependencies配置如下:
"devDependencies": { "archiver": "^0.11.0", "brfs": "^1.4.1", "browserify": "^11.2.0", "envify": "^3.0.0", "eslint": "^1.5.1", "fs-jetpack": "^0.7.0", "gulp": "^3.8.11", "gulp-base64": "^0.1.2", "gulp-file-include": "^0.13.7", "gulp-rename": "^1.2.0", "gulp-sass": "^2.1.0", "gulp-util": "^3.0.7", "gulp-wrap": "^0.11.0", "html2js-browserify": "0.0.2", "http-server": "^0.8.5", "vinyl-source-stream": "^1.1.0", "watchify": "^3.6.1", "yargs": "^1.3.1", "opener": "^1.4.1", "pre-commit": "^1.1.1", "pretty-hrtime": "^1.0.1" }
代码打包脚本如下:
var bundleTask = function () { return browserify({ entries: './myProj/background/main.js' }) .transform(envify) .bundle() .pipe(source('background.js')) .pipe(gulp.dest('build/background')); };
解答
报错和业务代码、AngularJS本身无关,核心原因是你使用的browserify版本过旧,和Manifest V3的Service Worker运行环境不兼容。
根因说明
- 你当前依赖的
browserify@11.2.0是2015年发布的老旧版本,它内置的Node.js核心模块浏览器端polyfill(主要是http/https模块的实现)初始化时,会主动读取global.XMLHttpRequest构造函数做接口封装。 - Manifest V3的后台脚本运行在Service Worker环境,不存在传统页面的
window顶层对象,而老版本browserify的全局对象探测逻辑存在缺陷,会自行生成一个空对象作为global命名空间,不会映射到Service Worker的真实全局作用域(self/globalThis),自然无法读取到真实全局下挂载的XMLHttpRequest构造函数,最终抛出类型错误。
注:Manifest V3的Service Worker环境原生支持XMLHttpRequest,不存在API移除的问题,只是全局对象映射错误导致无法读取到构造函数。
解决方法
按优先级尝试以下方案,均可解决该问题:
- 方案一(改造成本最低,优先尝试):在打包入口文件
./myProj/background/main.js的最顶部添加两行全局映射代码,手动将browserify识别的全局变量指向真实的全局作用域:
这两行代码同时可以解决AngularJS初始化时找不到window = globalThis; global = globalThis;window对象的后续兼容问题,添加后重新执行gulp打包,再加载扩展即可。 - 方案二:如果方案一未生效,修改browserify打包配置,通过
insertGlobalVars参数强制指定global变量的指向,调整后的打包脚本如下:var bundleTask = function () { return browserify({ entries: './myProj/background/main.js', insertGlobalVars: { global: function () { return 'globalThis'; } } }) .transform(envify) .bundle() .pipe(source('background.js')) .pipe(gulp.dest('build/background')); }; - 方案三(长期维护推荐):将browserify升级到17.0.0及以上版本,新版本已经修复了Service Worker环境下的全局对象探测逻辑,不需要额外添加hack代码。升级后如果部分transform插件出现兼容问题,对应升级插件版本即可。
快速定位技巧
如果调整后仍有同类报错,可以直接打开打包生成的build/background/background.js文件,搜索global.XMLHttpRequest关键词,就能看到具体是哪个依赖包调用了这段逻辑——你在源码里搜不到对应片段,是因为browserify打包时已经把所有依赖的代码合并到了同一个输出文件中。
内容的提问来源于stack exchange,提问作者Yamini Patel
相关产品推荐
相关产品推荐

