ES Modulesの活用例を考える
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タグを記述して読み込んでいました。
<!-- 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"
を指定することが必要です。
import $ from 'https://code.jquery.com/jquery-3.6.0.min.js'
$('.hoge').on('click', () => { ... })
<!-- 自作のJSファイルを読み込む -->
<script type="module" src="./js/main.js"></script>
モジュールシステムを使用することで、以下のメリットがあります。
- モジュールの補完が効く
- どこから読み込んでいるのかがわかりやすい
- スクリプト読み込み側の順番を気にする必要がない
importmapを使用する
先ほどの例では、import
の際にURLを指定しています。
ですが、URLを直接指定するのはあまり良くありません。URLが変わってしまうと、全てのファイルを修正する必要があるからです。
このような時に使用するのがimportmap
です。ライブラリ名を指定したインポートを利用できます。
以下はimportmap
を使用した例です。
import $ from 'jquery'
<!-- 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でフォームを実装してみます。
ちょっとしたサイト制作や、昔の環境にモダン技術を導入したい場合に有用です。
<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>
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を使用することで、より良いフロントエンド開発ができるのではないかと考えます。
参考サイト
Discussion