◆ nomodule で IE とモダンブラウザで実行するスクリプトを分ける
◆ モダンブラウザはネイティブに ESModules を使用
◆ IE は webpack でバンドルしたファイルを使用

IE と Chrome でユーザエージェント見て script タグの出し分けとかあんまり気が進まないなーとか思ってました
サーバ側の処理が入りますし
かと言って Chrome などでも IE 用の変換されたコードになると 本来のコードとかけ離れていて見づらいです

source map という機能はあるものの 見るだけならいいのですが ステップ実行など breakpoint を使って devtools で色々するには向いていません
元のコード通りのステップ実行にならず変に飛んだりすることがあります
また breakpoint 中で変数やプロパティを参照したり変更したりしようとすると 実際のコードとは違うためかアクセスできなかったり代入が反映されてないことも多々あります
なので source map は基本無効にしているのですが そうするとコードが何してるかわかりません
特に async とか混ざってくると原型がないです

実際のところ 開発用の webpack は Chrome のみ対象で公開用の webpack は IE 用みたいな設定にしてることがほとんどです
大抵の場合はこれでいいのですけどたまに開発中に IE でも動作確認してみるときとかに不便です
そもそも IE で動かす必要無い気がするのですが すでに動いてると切るタイミングが難しいです

nomodule

そんなとき ふと nomodule が頭に浮かびました!
noscript みたいなもので実際には特に使わないやつって扱いでしたがけっこう良い使い方ができそうな気がします

まず HTML ファイルでは次のように script タグを書きます

<script type="module" src="index.js"></script>
<script nomodule defer src="bundle.js"></script>

これで Chrome や Firefox は index.js を IE は bundle.js をロードできます

index.js は普通に ESModules で書いたエントリポイントです
これを webpack でバンドルした結果が bundle.js です
Chrome などの場合は そもそも webpack を使いません
ESModules で各ファイルをロードします

webpack だけでもインポート・エクスポートした部分が変換されてソースコードが見づらいケースが多々あるので 開発のしやすさはかなり上がります
ESModules だと node_modules の依存解決ができないので そこは Rollup でパッケージごとか全部で 1 ファイルのモジュールとしてエクスポートするよう変換しておきます

IE いらなくなったときに削るのが簡単だし Chrome のみだったのにあとから IE つけるのも楽な方法です
まぁいまさら後から IE 追加なんて絶対イヤですけど

どうでもいいところですが nomodule が node_modules に似てて無意識に nodmodule や nodemodule になってるのが困りどころです