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.
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!
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:
shelljs
package: yarn add -D shelljs
postinstall
in package.json
to: "postinstall": "node --preserve-symlinks --preserve-symlinks-main ./postinstall-patches.js && ngcc"
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:
socket.io-client/dist/socket.io.js
but with an additional "UMD shim" because it seems to be an "anonymous UMD" module, ORnpm_umd_bundle
magicSee 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With