📦

ES Modulesの活用例を考える

2023/10/14に公開

ES Modulesはご存知でしょうか。ファイルをモジュールという単位に分割し、必要な時に必要なモジュールを読み込む仕組みです。

私の体験談ですが、レガシー環境でバンドラーを使用できない状況がありました。外部ライブラリを使用する必要がありましたが、CDNを別に読み込むことはHTMLファイルとの密結合を発生させるため避けたいところです。

どうすれば良いか考えた時に、ES Modulesを使用することで解決できました。

本記事では、ブラウザでの使用を想定したES Modulesを使用した例を紹介します。

ES Modulesとは

改めて、ES ModulesはJavaScriptのモジュールシステムです。ECMAScript 2015のModulesの標準仕様として策定されています。

JavaScriptのコードをモジュールという単位に分割し、必要な時に必要なモジュールを読み込む仕組みです。そのおかげで、JavaScriptのコードを再利用しやすくなります。また、依存関係を明確にすることで、コードの保守性を高めることができます。

以下のような形で使用します。

import { hoge } from './hoge.js'

モジュールシステムがなかった時代

モジュールシステムが誕生する以前は、外部ファイルを読み込む際、HTMLファイルにscriptタグを記述して読み込んでいました。

index.html
<!-- jQueryを読み込む -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- 自作のJSファイルを読み込む -->
<script src="./js/main.js"></script>

ですが、記述順を間違えるとエラーになってしまいます。
またHTMLとJavaScriptが密結合になってしまうため、メンテナンス性が低くなってしまいます。

どうやって使うのか

ここではHTMLに外部JavaScriptファイルを読み込む前提で話を進めます。

基本的な使い方

以下はブラウザネイティブES Modulesを使用した例です。
type="module"を指定することが必要です。

main.js
import $ from 'https://code.jquery.com/jquery-3.6.0.min.js'

$('.hoge').on('click', () => { ... })
index.html
<!-- 自作のJSファイルを読み込む -->
<script type="module" src="./js/main.js"></script>

モジュールシステムを使用することで、以下のメリットがあります。

  • モジュールの補完が効く
  • どこから読み込んでいるのかがわかりやすい
  • スクリプト読み込み側の順番を気にする必要がない

importmapを使用する

先ほどの例では、importの際にURLを指定しています。
ですが、URLを直接指定するのはあまり良くありません。URLが変わってしまうと、全てのファイルを修正する必要があるからです。

このような時に使用するのがimportmapです。ライブラリ名を指定したインポートを利用できます。

以下はimportmapを使用した例です。

main.js
import $ from 'jquery'
index.html
<!-- importmapを指定する -->
<script type="importmap">
{
  "imports": {
    "jquery": "https://code.jquery.com/jquery-3.6.0.min.js"
  }
}
</script>
<!-- 自作のJSファイルを読み込む -->
<script type="module" src="./js/main.js"></script>

モジュール名でエイリアス登録することで、可読性の向上やURL変更時の修正の手間を減らすことができます。

(実演)Vueを使ってフォームを実装する

ブラウザネイティブES Modulesを使用し、Vueでフォームを実装してみます。
ちょっとしたサイト制作や、昔の環境にモダン技術を導入したい場合に有用です。

index.html
<div id="app"></div>

<script type="importmap">
  {
    "imports": {
      "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
    }
  }
</script>
<script type="module" src="./form.js"></script>
form.js
import { createApp, ref } from 'vue'

const Form = createApp({
  setup() {
    const name = ref('')
    const email = ref('')

    const handleSubmit = () => {
      alert(`name: ${name.value}, email: ${email.value}`)
    }

    return {
      name,
      email,
      handleSubmit
    }
  },
  template: `
    <form @submit.prevent="handleSubmit">
      <div>
        <label for="name">名前</label>
        <input type="text" id="name" v-model="name" required>
      </div>
      <div>
        <label for="email">メールアドレス</label>
        <input type="email" id="email" v-model="email" required>
      </div>
      <input type="submit" value="送信" />
    </form>
  `
})

Form.mount('#app')

バンドラーは不要になるのか

LPサイト制作や昔の環境にモダン技術を導入したい場合、ブラウザネイティブES Modulesは有用です。
それでバンドラーが不要になるかというと、そうではないと考えています。

実際、多くのフロントエンド開発では、バンドラーを使用しています。以下のような場合はバンドラーが必須ではないかと考えます。

  • npmを使用したパッケージ管理している
  • SCSS、TypeScript、ReactのJSX構文のコンパイラーが絡んでくる
  • サイト制作に関して、画像やCSSをJSにまとめてバンドルしたい

まとめ

本記事では、ブラウザネイティブES Modulesを使用した例を紹介しました。

先ほど述べましたが、バンドラーが不要になるかというと、そうではないと考えています。
適材適所でブラウザネイティブES Modulesを使用することで、より良いフロントエンド開発ができるのではないかと考えます。

参考サイト

https://developer.mozilla.org/ja/docs/Web/HTML/Element/script/type/importmap#ブラウザーの互換性

https://ics.media/entry/16511/#モジュールバンドラーとの比較

Discussion