Bazel + Angular + SocketIO原因:未捕获的TypeError:XMLHttpRequest不是构造函数 [英] Bazel + Angular + SocketIO Causes: Uncaught TypeError: XMLHttpRequest is not a constructor
问题描述
我想将 ngx-socket-io 添加到我的Angular应用程序中.我使用Bazel运行我的Angular开发服务器.不幸的是, ngx-socket-io
似乎无法与 ts_devserver
一起使用.我在浏览器控制台中收到此错误:
未捕获的TypeError:XMLHttpRequest不是构造函数在ts_scripts.js?v = 1587802098203:16776在Object.23 .../transport(ts_scripts.js?v = 1587802098203:16780)在o(ts_scripts.js?v = 1587802098203:11783)
这似乎是由 xmlhttprequest-ssl 引起的,它与需要它ngx-socket-io
.但是,仅在 ts_devserver 时才会出现此问题.在生产中运行Angular应用完全正常.
最低繁殖量
您可以轻松地自己尝试: https://github.com/flolu/bazel-socketio-问题
只需运行 yarn install
,然后运行 yarn dev
(它会在浏览器控制台中导致错误@ http://localhost:4200 ).并且请注意, yarn prod
@ http://localhost:8080 可以正常工作!
编辑1
当前在Windows上似乎还有另一个问题.因此,只有在运行Mac或Linux的情况下,您才可以尝试示例存储库
问题来自 engine.io-client
,由 socket.io-client
:
当 socket.io-client
作为UMD模块触发时构建,
"@ npm//socket.io-client:socket.io-client__umd",
在 BUILD.bazel
中, engine.io-client/package.json
的浏览器
键:
浏览器":{"ws":否,"xmlhttprequest-ssl":"./lib/xmlhttprequest.js"},
似乎被忽略了.
结果, node_modules/engine.io-client/lib/transports/*.js
中的 require('xmlhttprequest-ssl')
语句保留在UMD构建.由于 xmlhttprequest-ssl
用于无头Node环境,并且不能在浏览器中工作,因此会导致错误.
我找不到此行为的原因/问题,但我找到了解决方案(不应将其视为解决方法):
使用 postinstall
脚本重写 engine.io-client
:
- 安装
shelljs
软件包:yarn add -D shelljs
- 将
package.json
中的postinstall
更新为:"postinstall":"node --preserve-symlinks --preserve-symlinks-main ./postinstall-patch.js&& ngcc"
- 将以下代码放入项目根目录下的
postinstall-patches.js
中:
try {require.resolve('shelljs');}抓住(e){//我们在一个由bazel管理的外部node_modules存储库中//并且解析失败,因为节点未保留符号链接//加载脚本时.//这可以使用--preserve-symlinks-main标志修复,该标志//在节点10.2.0中引入console.warn(`在外部存储库中运行postinstall-patches.js脚本需要在节点10.2.0中引入--preserve-symlinks-main节点标志.`+`当前节点版本为$ {process.version}.用'$ {process.argv.join('')}'.`)调用的节点;process.exit(0);}const {set,cd,sed,ls} = require('shelljs');const path = require('path');const log = console.info;log('=====将要运行postinstall-patches.js脚本=====');//发生第一个错误时失败set('-e');//打印正在执行的命令set('-v');cd(__ dirname);日志('\ n#补丁引擎.io-客户端:将\'xmlhttprequest-ssl \'重写为浏览器shim');ls('node_modules/engine.io-client/lib/transports/*.js').forEach(function(file){sed('-i','\'xmlhttprequest-ssl \'','\'../xmlhttprequest \'',文件);});log('=====完成运行postinstall-patches.js脚本=====');
(灵感: https://bazelbuild.github.io/rules_nodejs/#patching-the-npm-packages ,它链接到示例 https://github.com/angular/angular/blob/master/tools/postinstall-patches.js )
-
纱线安装
-
yarn dev
我将在几分钟后向您的GitHub repro提交拉取请求.
可能替代方案,无法使它们起作用:
- 使用
socket.io-client/dist/socket.io.js
,但附加一个"UMD垫片",因为它似乎是一个匿名UMD"模块,或者 - 一些
npm_umd_bundle
魔术
请参阅问题每个新的npm dep都需要一种独特的方法来将其添加到ts_devserver#1055 在 bazelbuild/rules_nodejs
中,以获取有关这两种方式的更多信息./p>
I want to add ngx-socket-io to my Angular application. I use Bazel to run my Angular dev-server.
Unfortunately ngx-socket-io
doesn't seem to work with the ts_devserver
out of the box. I get this error in the browser console:
Uncaught TypeError: XMLHttpRequest is not a constructor
at ts_scripts.js?v=1587802098203:16776
at Object.23.../transport (ts_scripts.js?v=1587802098203:16780)
at o (ts_scripts.js?v=1587802098203:11783)
It seems to be caused by xmlhttprequest-ssl which is a dependency of engine.io-client and it is needed by ngx-socket-io
. But this problem only occurs with the ts_devserver. Running the Angular app in production works totally fine.
Minimal Reproduction
You can easily try it yourself: https://github.com/flolu/bazel-socketio-issue
Just run yarn install
and then yarn dev
(it causes the error in the browser console @ http://localhost:4200).
And note that yarn prod
@ http://localhost:8080 works just fine!
Edit 1
Currently there seems to be another issue on Windows. So you can only try the example repo if you're running Mac or Linux
The problem comes from engine.io-client
, which is used internally by socket.io-client
:
When socket.io-client
gets built as UMD module triggered by
"@npm//socket.io-client:socket.io-client__umd",
in BUILD.bazel
, the browser
key of engine.io-client/package.json
:
"browser": {
"ws": false,
"xmlhttprequest-ssl": "./lib/xmlhttprequest.js"
},
is seemingly ignored.
As a consequence, the require('xmlhttprequest-ssl')
statements in node_modules/engine.io-client/lib/transports/*.js
remain in the UMD build. Because xmlhttprequest-ssl
is intended for headless Node environments and does not work in browsers, this results in an error.
I couldn't find a reason/issue for this behavior, but I found a solution (which shouldn't be considered as a workaround):
Rewrite engine.io-client
with a postinstall
script:
- install
shelljs
package:yarn add -D shelljs
- update
postinstall
inpackage.json
to:"postinstall": "node --preserve-symlinks --preserve-symlinks-main ./postinstall-patches.js && ngcc"
- put the following code into
postinstall-patches.js
at project root:
try {
require.resolve('shelljs');
} catch (e) {
// We are in an bazel managed external node_modules repository
// and the resolve has failed because node did not preserve the symlink
// when loading the script.
// This can be fixed using the --preserve-symlinks-main flag which
// is introduced in node 10.2.0
console.warn(
`Running postinstall-patches.js script in an external repository requires --preserve-symlinks-main node flag introduced in node 10.2.0. ` +
`Current node version is ${process.version}. Node called with '${process.argv.join(' ')}'.`);
process.exit(0);
}
const {set, cd, sed, ls} = require('shelljs');
const path = require('path');
const log = console.info;
log('===== about to run the postinstall-patches.js script =====');
// fail on first error
set('-e');
// print commands as being executed
set('-v');
cd(__dirname);
log('\n# patch engine.io-client: rewriting \'xmlhttprequest-ssl\' to browser shim');
ls('node_modules/engine.io-client/lib/transports/*.js').forEach(function (file) {
sed('-i', '\'xmlhttprequest-ssl\'', '\'../xmlhttprequest\'', file);
});
log('===== finished running the postinstall-patches.js script =====');
(Inspiration: https://bazelbuild.github.io/rules_nodejs/#patching-the-npm-packages, which links to the example https://github.com/angular/angular/blob/master/tools/postinstall-patches.js)
yarn install
yarn dev
I'll submit a pull request to your GitHub repro in a few minutes.
Possible alternatives, couldn't get them to work:
- use
socket.io-client/dist/socket.io.js
but with an additional "UMD shim" because it seems to be an "anonymous UMD" module, OR - some
npm_umd_bundle
magic
See issue Every new npm dep needs a unique approach how to add it to ts_devserver #1055 in bazelbuild/rules_nodejs
for more information about both ways.
这篇关于Bazel + Angular + SocketIO原因:未捕获的TypeError:XMLHttpRequest不是构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!