web-dev-qa-db-ja.com

Bazel + Angular + SocketIO原因:キャッチされなかったTypeError:XMLHttpRequestはコンストラクタではありません

ngx-socket-io をmy Angularアプリケーションに追加します。Bazelを使用してmy Angular dev-serverを実行します。残念ながら、ngx-socket-ioは、そのままではts_devserverで動作しないようです。ブラウザコンソールで次のエラーが発生します。

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)

engine.io-client の依存関係である xmlhttprequest-ssl が原因であると思われ、ngx-socket-ioが必要とします。ただし、この問題は ts_devserver でのみ発生します。 Angularアプリを production で実行すると、まったく問題なく動作します。

最小限の複製

自分で簡単に試すことができます。 https://github.com/flolu/bazel-socketio-issue

yarn installを実行してからyarn devを実行するだけです(ブラウザコンソールでエラーが発生します@ http:// localhost:42 )。 yarn prod @ http:// localhost:808 は問題なく機能することに注意してください。

編集1

現在、Windowsには別の問題があるようです。したがって、MacまたはLinuxを実行している場合にのみ、サンプルリポジトリを試すことができます

13
Florian

問題は、_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_のbrowserキー:

_ "browser": {
   "ws": false,
   "xmlhttprequest-ssl": "./lib/xmlhttprequest.js"
 },
_

無視されているようです。

結果として、_node_modules/engine.io-client/lib/transports/*.js_のrequire('xmlhttprequest-ssl')ステートメントはUMDビルドに残ります。 _xmlhttprequest-ssl_はヘッドレスNode環境用であり、ブラウザでは機能しないため、エラーが発生します。

この動作の理由/問題を見つけることはできませんでしたが、解決策を見つけました(回避策とは見なされません)。

_engine.io-client_をpostinstallスクリプトで書き換えます。

  1. インストールshelljsパッケージ:_yarn add -D shelljs_
  2. _package.json_のpostinstallを_"postinstall": "node --preserve-symlinks --preserve-symlinks-main ./postinstall-patches.js && ngcc"_に更新します
  3. 次のコードをプロジェクトルートの_postinstall-patches.js_に挿入します。
_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 =====');
_

(インスピレーション: https://bazelbuild.github.io/rules_nodejs/#patching-the-npm-packages 、例へのリンク https://github.com/angular/ angular/blob/master/tools/postinstall-patches.js

  1. _yarn install_
  2. _yarn dev_

数分後にプルリクエストをGitHub再現に送信します。


可能な代替、それらを機能させることができませんでした:

  • _socket.io-client/dist/socket.io.js_を使用しますが、「匿名UMD」モジュールのように見えるため、追加の「UMDシム」を使用します。または
  • いくつかの_npm_umd_bundle_マジック

両方の方法の詳細については、問題 すべての新しいnpm depにts_devserver#1055に追加する独自のアプローチが必要です_bazelbuild/rules_nodejs_ を参照してください。

5
Sebastian B.