

npmで入れたグローバル汚染（グローバルスコープに変数や関数を定義）している外部のライブラリをWebpackでバンドルした場合、グローバル汚染の問題は解消されますか？（Webpackでいい感じにしてくれますか？）  
そうでない場合、外部ライブラリがグローバル汚染しているかどうか分かる方法などはありますか？


CC BY-SA 4.0
2022-10-12T17:42:29.917
91570
2022-10-19T10:27:13.990
40137
question
javascript webpack
Webpackを使用すればグローバル汚染は起こりませんか？


いいえ、webpackはグローバル汚染を完全に防いでくれません。これはwebpackの限界と言うより、ESモジュール、CommonJS、AMDの限界です。

webpackはCommonJSやAMDを用いてモジュール化されたJavaScript群を一つのJavaScriptとして結合するために作られました。ES2015からECMAScriptの仕様自体にモジュールの機能(ESモジュール)が加わり、最新のwebpackはESモジュールにも対応しました。現在において、ESモジュールを用いることが多いかと思いますので、以下、主にESモジュールを使用している場合について述べますが、CommonJS等でもほぼ同じかと思います。

まず、グローバル変数が定義されたり上書きされる場合は次のパターンです。

  1. トップレベルで`var`を用いた変数宣言や`function`を用いた関数宣言。
  2. 非strictモードで、宣言されていない変数への代入。
  3. グローバルオブジェクトのプロパティへの代入。

上記のうち2については、既に推奨されない方法であり、また、ESモジュールでは必ずstrictモードになるため、無視していいかと思います。(非strictモードでないと動作しないコードは古すぎて保守されていないと考えられるため、そもそも使用しない方が良いでしょう)

JavaScriptの黎明期、もっとも問題だったものの一つがが1によってグローバル変数がどんどん作られてしまうことです。ブラウザで複数のJavaScriptを読み込んだ場合、それぞれのトップレベルにあった変数や関数は勝手にグローバル変数になってしまうため、変数のコンフリクトなどが起きることがありました。これが所謂グローバル汚染というものです。グローバル変数化を防ぐためにIIFE等のテクニックが必要になるなど、JavaScriptをやけに難しいものにしていました。そのような状況で生まれたのがCommonJS等のモジュール化技術です。さらに、それらの技術を参考にESモジュールが仕様として策定され、普及していくことになりました。

ESモジュールなどのモジュール化技術が防ぐことは1のみです。その仕組みは単純で、トップレベルをトップレベルでは無いスコープとするということです。IIFEが自動的に入っているといっても良いでしょう。各変数はモジュール内に閉じ込められ、必要なものだけexportしてimportするようにしました。これによって、グローバル汚染の問題はほとんど無くなりました。

こうやってほとんどの場合は解決できたのですが、3がいまだに残っています。JavaScritpのグローバル変数はグローバルオブジェクトのプロパティでもあるので、グローバルオブジェクトを直接変えられてしまえば、それを防ぎようはありません。webpackを使おうが、純粋なESモジュールとして作ろうが、`globalThis.x
= 42;`みたいに書かれた場合は、結局グローバル変数`x`が全ての所に現れてしまいます。

ただ、これが絶対に悪いというわけではありません。例えば、Polyfillのような仕組みはグローバル変数を再定義出来なければ実現出来ないでしょう。HTMLでのonclick等で直接関数を呼び出したいというのもあるでしょうが、それもグローバル変数でなければ使えません。グローバル変数は必要最低限にすべきではありますが、できなくなればなったで、困ったことになってしまうので、仕方がない面があるのだと思います。ただ、(Polyfill等を除き)多数のグローバル変数を定義するようなライブラリは行儀が悪いと言うべきなので、使うできではないかと思います。

なお、グローバル汚染されているかどうかですが、グローバルオブジェクトのプロパティを網羅的に調べるぐらいしか無いかと思います。


CC BY-SA 4.0
2022-10-19T10:27:13.990
91680
2022-10-19T10:27:13.990
7347
91570
answer