2018年1月7日日曜日

【Node.js】Dynamic importをウェブサービスで使うときの注意点

あけましておめでとうございます。今年もよろしくおねがいします。

去年のクリスマスイブに書こうとしていた、V8の最新版に関連するネタを新年最初の記事にします。


Dynamic importとは

読んで字のごとく「動的な輸入」です。詳しくは、同僚がNode.js Advent Calendarに投稿した記事を参照してください。

簡単に言うと、
必要なときに必要なモジュールだけインポートできるので便利っちゃ便利なんですが、ウェブサービスのサーバサイドで使う場合は注意が必要です。

何が問題?

たとえばこういう状況を仮定します。
  • http://example.com/a へのアクセスで、モジュールAが動的にインポートされる
  • このページは、サーバ起動後まだ一度もアクセスされていない。つまりモジュールAもまだロードされていない
この状況で、リファクタリングなり仕様変更なりでモジュールAのファイルがなくなった(リネーム・移動を含む)としましょう。もちろん呼び出し側はそれに合わせてインポートファイル名を変えます。

さて、ソースが変更されたらサーバを再起動しないといけませんが、モジュールファイルがなくなってから再起動されるまでの間に http://example.com/a にアクセスがあったとき、存在しないファイルをインポートしようとしてエラーが発生します。

これはDynamic importに限らず、従来のrequireでも同じことが言えます。

対策は?

ひとつの考えはノーガード戦法。一度もアクセスがないページでしか起きないし、再起動はせいぜい数秒だし、そこに当たった人は運がなかったってことで。

とはいっても商用サービスの場合は信用に影響することもあるし、何より対策しないのと対策できないのでは大違い。なんとか対策を考えましょう。

ファイルを残しておいたら…?

「ファイルがなくなるのが問題なら、元のファイルはサーバ再起動後に消せばいいじゃない」と考える人もいるかもしれません。

やはりリファクタリングなり仕様変更なりでモジュールの中身が変更された(エクスポートした関数の引数が変更されたなど)場合、インポートは成功しますが、想定したものと違うものがインポートされるので今度は使用するときにエラーが起きてしまいます。

Dynamic importを使わない

見も蓋もない対策ですが、ぶっちゃけこれが一番確実で簡単です。

これまでどおりすべてグローバルスコープでimportしてしまえば、サーバ起動時にすべてのモジュールがインポートされてオンメモリで動作します。その後でモジュールファイルが削除されても問題ありません。

そもそもサーバサイドで動かすなら最初に全部ロードしたほうが効率的です。

どうしても使いたい場合は…

先祖代々伝わる家訓や宗教上の理由でどうしてもDynamic importを使いたい場合は、サーバを冗長構成にしてソース変更・再起動時にバランサから切り離しましょう。

変更と再起動をオフラインで行えば文句を言われることはありません。

0 件のコメント:

コメントを投稿