Edited at

ng build --prodではまった話


ng build --prodは最適化ビルド

「最適化」ってのは具体的に何してんだかわかんないけど、cssやjsのpackみたいなもんかなって思ってたんですよ。実際--prodでビルドした後のmain.jsは一行になってたし、そんなところだろうと・・・。


朧げな理解しかしてなかった「最適化」にはまる

先日、本番環境のみ動作しないコードがあって、開発環境やステージング環境ではもちろん正しく動いているんだけど、まあ、あるあるだよねと環境面から切り分けをしていたわけなんですが、どうも原因がわからない。仕方ないのでデバッグコード仕込んでいろいろ見てたら、ng buildの--prodによる最適化により処理が変わってしまっていたコードがあったことが原因でした。


obj.constructor.nameは使っちゃダメ

結論から言うと、これでした。

本番と開発環境で設定により処理を切り替えたいロジックがあって、設定値とクラス名の突合で切り替えるようなロジックを書いていたんです。以下みたいな感じ

    for (let pub of this.publishers) {

if(env_publishers.includes(pub.constructor.name)) {
// 確認用
console.log('pub name is ->' + pub.constructor.name);
// 設定されたpublisherのみ使う
await pub.exec(entry);
}
}

publisherのクラス名をobj.constructor.nameで取得し、それが設定値の配列に含まれるかを判定したかったんですよ。

ステージングや開発環境では問題なく動作していて、console.logの出力も

 pub name is ->hogehoge

ってなるんですが、ng build --prodをデプロイした環境では

 pub name is ->e

ってなってました。

そんなバカな・・・って思い、console.dirでpublishersを出力してみたら

Array(2)

0: hogehoge {_myFunction: t, _apiPath: "/hogeratta"}
1: fugafuga {_myFunction: t, _apiPath: "/fugaratta"}
length: 2
__proto__: Array(0)

って開発環境でなってるのが、

Array(2)

0: e {_myFunction: t, _apiPath: "/hogeratta"}
1: e {_myFunction: t, _apiPath: "/fugaratta"}
length: 2
__proto__: Array(0)

みたいになってました。。。

おいおい、最適化ってそこまでやるのかよ、と・・・

その後改めて調べてみたら、本家のissueにも以下のように書かれてました。

so it is a recommendation not to use constructor.name.

そ、そうですか・・・。

一応バグらしいですが、closeされちゃっていて修正される気配ないのでinstanceof使っておきます。という話でした。