JavaScriptでは他のJSファイルを読み込みES Modulesという仕組みがあり、Chrome、Edge、Safariなどブラウザのサポートが拡大しつつあります(参考記事「JavaScriptでモジュールを使う時代に! ブラウザで覚えるES Modules入門」)。
さらに、モジュールをimport()
を使って「関数のように」呼び出すためのdynamic importという仕組みが策定中(※ tc39/proposal-dynamic-import)です。Safari 11、Chromeの次期バージョン63ではモジュールのdynamic importに対応しており、ブラウザでその挙動を確認できます。
dynamic importのメリットは、任意のタイミングでモジュールを読み込めること。例えば、ページの初期表示に必要なJavaScriptだけを読み込んでおき、コンテンツが展開する度に必要なモジュールを遅延ロードすれば、ページの初期表示時の処理負荷が軽減できます。
本エントリーでは次のようなSub
クラスを定義したsub.js
モジュールの読み込みを通して、dynamic importの使い方について解説します。
export class Sub {
subMethod() {
alert("this is Sub Class Method");
}
}
各サンプルは、Safari 11かChrome 63以降(Chrome Canaryを用いるとよい)で確認できます。
これまでのimport
これまでのimport
は、 import
はJavaScriptのトップレベルでしか用いることができず、モジュールは即座に読み込まれる仕様でした。
// 即座にsub.jsが読み込まれる
import {Sub} from './sub.js'
const sub = new Sub();
sub.subMethod(); // 「this is Sub Class Method」というアラートが表示される。
dynamic import
Dynamic importでは、 import(モジュール名)
を用いてモジュールを動的に読み込みます。返り値はPromise
(Promise - JavaScript | MDN)です。
// import()のタイミングでsub.jsが読み込まれる
import('./sub.js')
.then(module => {
// 動的に読み込まれたSubクラス
const sub = new module.Sub();
sub.subMethod();
});
resolve()
時の引数にモジュールを受け取るため、new module.Sub()
とすればsub.js
内のSub
クラスにアクセスできます。
※ dynamic importに対応したブラウザでご確認ください。
await/asyncを用いてimport
返り値が Promise
なので、 await と asyncを用いて、次のようにモジュールの読み込みを待つことも可能です。
async function main() {
const module = await import('./sub.js');
const sub = new module.Sub();
sub.subMethod();
}
main();
※ dynamic importに対応したブラウザでご確認ください。
一定時間後にimport
モジュールが動的に読み込まれていることをわかりやすくするために、次のように2秒後にモジュールの読み込み・実行を行う処理を書きました。
setTimeout(() => {
import('./sub.js') // 2秒後にモジュールを読み込み
.then(module => {
// 読み込み完了後にSubを使用する
const sub = new module.Sub();
sub.subMethod();
});
}, 2000);
※ dynamic importに対応したブラウザでご確認ください。
Chromeの開発者ツールで確認すると、ページ表示時にはモジュールは読み込まれず、2秒経って読み込まれることが確認できます。
Safariでは現行版で対応済
Safariは現行版の11でdynamic importに対応済。ちなみにiOS Safariでも動作します。
ますます強力になるJavaScriptのモジュール
JavaScriptの大規模開発においてはモジュールによる処理の分割は必須。従来はwebpack(参考記事「最新版で学ぶwebpack 3入門」)やBrowserifyを用いて実現していた仕組みが、ブラウザの標準機能として実装されつつあり、さらに動的読み込みもというのは明るい話題ではないでしょうか。