Help us understand the problem. What is going on with this article?

全モダンブラウザで使えるJavaScriptのdynamic import(動的読み込み)

JavaScriptでは他のJSファイルを読み込みES Modulesという仕組みがあり、Chrome、Edge、Safariなどブラウザのサポートが拡大しつつあります(参考記事「JavaScriptでモジュールを使う時代に! ブラウザで覚えるES Modules入門」)。

さらに、モジュールをimport()を使って「関数のように」呼び出すためのdynamic importという仕組みが2020年に公開されるECMAScriptの仕様で導入されます(tc39/proposal-dynamic-import)。Google Chrome、Firefox、Safariではではモジュールのdynamic importに対応しており、ブラウザでその挙動を確認できます。

dynamic importのメリットは、任意のタイミングでモジュールを読み込めること。たとえば、ページの初期表示に必要なJavaScriptだけを読み込んでおき、コンテンツが展開する度に必要なモジュールを遅延ロードすれば、ページの初期表示時の処理負荷が軽減できます。

本エントリーでは次のようなSubクラスを定義したsub.jsモジュールの読み込みを通して、dynamic importの使い方について解説します。

sub.js
export class Sub {
  subMethod() {
    alert("this is Sub Class Method");
  }
}

各サンプルは、Google Chrome、Safari、Firefox、Edgeで動作します。

これまでのimport

importはJavaScriptのトップレベルでしか用いることができず、モジュールは即座に読み込まれる仕様でした。

main1.js
 // 即座にsub.jsが読み込まれる
import {Sub} from './sub.js'

const sub = new Sub();
sub.subMethod(); // 「this is Sub Class Method」というアラートが表示される。

dynamic import

Dynamic importでは、 import(モジュール名)を用いてモジュールを動的に読み込みます。返り値はPromisePromise - JavaScript | MDN)です。

main2.js
// 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 なので、 awaitasyncを用いて、次のようにモジュールの読み込みを待つことも可能です。

main3.js
async function main() {
  const module = await import('./sub.js');
  const sub = new module.Sub();
  sub.subMethod();
}

main();

※ dynamic importに対応したブラウザでご確認ください。

image.png

一定時間後にimport

モジュールが動的に読み込まれていることをわかりやすくするために、次のように2秒後にモジュールの読み込み・実行を行う処理を書きました。

main4.js
setTimeout(() => {
  import('./sub.js')  // 2秒後にモジュールを読み込み
    .then(module => {
        // 読み込み完了後にSubを使用する
        const sub = new module.Sub();
        sub.subMethod();
      });
}, 2000);

※ dynamic importに対応したブラウザでご確認ください。

Chromeの開発者ツールで確認すると、ページ表示時にはモジュールは読み込まれず、2秒経って読み込まれることが確認できます。

SafariやFirefox、Edgeでも動作

Safariは11.1から、Firefoxでは67から、Edgeでは79からdynamic importに対応済みです。ちなみにiOS Safariでも動作します。

Can I useより

Firefox、Safariで動作している様子は次のとおりです。

▼ Firefoxで動作している様子

▼ Safariで動作している様子

オブジェクト形式でモジュールを展開する

前述の例では .then(module =>のようにmodule変数にモジュールを展開していましたが、次のようにするとnew Sub()Subをインスタンス化できるようになります。

この方法は「tc39/proposal-dynamic-import」に記載はありませんでしたが、Safari 11、Chrome 64 (canary)で動作しました。

main5.js
import('./sub.js')
  .then(({ Sub }) => {
  // 動的に読み込まれたSubクラス
  const sub = new Sub();
  sub.subMethod();
});

await / asyncを使うとこのようになります。

main6.js
async function main() {
  const { Sub } = await import('./sub.js');

  const sub = new Sub();
  sub.subMethod();
}

main();

※ dynamic importに対応したブラウザでご確認ください。

複数クラスのimport

オブジェクト形式で展開する場合、複数のクラスをimportするならば次のようにします。

main.js
async function main() {
  const { Sub, Sub2 } = await import('./sub.js');

  const sub = new Sub();
  sub.subMethod();

  const sub2 = new Sub2();
  sub2.subMethod2();
}

main();

※ dynamic importに対応したブラウザでご確認ください。

ますます強力になるJavaScriptのモジュール

JavaScriptの大規模開発においてはモジュールによる処理の分割は必須。従来はwebpack(参考記事「最新版で学ぶwebpack 3入門」)やBrowserifyを用いて実現していた仕組みが、ブラウザの標準機能として実装されつつあり、さらに動的読み込みもというのは明るい話題ではないでしょうか。

参考記事

tonkotsuboy_com
ICSのインタラクションデザイナーです。「JavaScriptコードレシピ集」の著者。CSS Nite 2017・2018でベストセッションの1人に選出されました。 アプリ開発やWebページ制作が専門で、フロントエンドの情報を随時発信しています。猫の名前は「うに」です。九州大学芸術工学部音響設計学科出身。
https://ics.media
ics
インタラクションデザイン専門のプロダクション。最先端のウェブテクノロジーを駆使し、オンスクリーンメディアの表現分野で活動しています。最新のウェブ技術を発信するサイト「ICS MEDIA」を運営。
https://ics.media/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした