必要以上にBabelの変換が入ると思ったら、Babelの裏機能とそれを制御する新機能を知ってしまいました。
起きていた状況
ブラウザJavaScriptをBabelで変換していたのですが、.browseslistrcでIE11を除外した最新設定にしているのも関わらず、Optional Chaining(?.)や、デフォルト引数、引数内でのスプレッドといったものが変換されてしまう状態が続いていました。
@babel/preset-envにexcludeを明示すると止まるので、@babel/preset-envが挿入しているとわかったところでさらに調査を進めていました。
裏機能…ブラウザごとのバグの吸収
今回調べてみるまで知らなかったのですが、@babel/preset-envによる変換は、ブラウザネイティブでサポートしないもの…だけではなく、ブラウザごとのバグ回避も含んで処理を行っていました。
ところが、@babel/preset-envが処理を選択できるのは、@babel/plugin-transform-function-parametersといったプラグイン単位であるため、ごくわずかなパターンでバグが起きる場合にもプラグインを全部入れる、ということとなってしまい、バグを踏まないコードまで変換されて冗長となる事態となっていました。
新機能…bugfixes
このような状態を解決するため、「不具合の出るところだけ変換する」ための@babel/preset-modulesというパッケージが作られ、Babel 7.9になって@babel/preset-envへ組み込まれ、bugfixes: trueという設定を行うことで利用可能となっています。
実際に設定をかけてみたところ、?.の変換で余計なvarが現れたり、引数の変換でargumentsとfunctionになってしまったり、と言った箇所がきれいに解消しました。