去年のクリスマスイブに書こうとしていた、V8の最新版に関連するネタを新年最初の記事にします。
Dynamic importとは
読んで字のごとく「動的な輸入」です。詳しくは、同僚がNode.js Advent Calendarに投稿した記事を参照してください。簡単に言うと、
- ECMAScriptのimport構文はグローバルスコープじゃないと使えない
- Dynamic importを使うと、どこでも使えるようになる
- インポートは非同期に行われ、Promiseオブジェクトを返す
何が問題?
たとえばこういう状況を仮定します。- http://example.com/a へのアクセスで、モジュールAが動的にインポートされる
- このページは、サーバ起動後まだ一度もアクセスされていない。つまりモジュールAもまだロードされていない
さて、ソースが変更されたらサーバを再起動しないといけませんが、モジュールファイルがなくなってから再起動されるまでの間に http://example.com/a にアクセスがあったとき、存在しないファイルをインポートしようとしてエラーが発生します。
これはDynamic importに限らず、従来のrequireでも同じことが言えます。
対策は?
ひとつの考えはノーガード戦法。一度もアクセスがないページでしか起きないし、再起動はせいぜい数秒だし、そこに当たった人は運がなかったってことで。とはいっても商用サービスの場合は信用に影響することもあるし、何より対策しないのと対策できないのでは大違い。なんとか対策を考えましょう。
ファイルを残しておいたら…?
「ファイルがなくなるのが問題なら、元のファイルはサーバ再起動後に消せばいいじゃない」と考える人もいるかもしれません。やはりリファクタリングなり仕様変更なりでモジュールの中身が変更された(エクスポートした関数の引数が変更されたなど)場合、インポートは成功しますが、想定したものと違うものがインポートされるので今度は使用するときにエラーが起きてしまいます。
Dynamic importを使わない
見も蓋もない対策ですが、ぶっちゃけこれが一番確実で簡単です。これまでどおりすべてグローバルスコープでimportしてしまえば、サーバ起動時にすべてのモジュールがインポートされてオンメモリで動作します。その後でモジュールファイルが削除されても問題ありません。
そもそもサーバサイドで動かすなら最初に全部ロードしたほうが効率的です。
どうしても使いたい場合は…
先祖代々伝わる家訓や宗教上の理由でどうしてもDynamic importを使いたい場合は、サーバを冗長構成にしてソース変更・再起動時にバランサから切り離しましょう。変更と再起動をオフラインで行えば文句を言われることはありません。
0 件のコメント:
コメントを投稿