クモのようにコツコツと

フロントエンドエンジニア イイダリョウのブログ。略称「クモコツ」

【JS】モジュール(import / export)でどんなことができるのか事始めてみた

Vue.jsやNuxt.jsを理解する上で重要なJSの「モジュール」という仕組みを先に理解する。外部JSファイルの一部の機能を読み込むようだが、どんなことがことができるのか。それではいきましょう!

【目次】

JSファイル読み込み

これまで、HTMLファイルに外部のJSファイルを読み込むときはこうしていた。

<script src="js/hoge.js"></script>

ファイルごと読み込むのでだんだん増えていく運命…。

<script src="js/hoge1.js"></script>
<script src="js/hoge2.js"></script>
<script src="js/hoge3.js"></script>
<script src="js/hoge4.js"></script>

デメリットもある。

  • ファイルの中の一部の機能しか使わないのにファイルごと読まなければならない
  • 上から順番に読むので、読み込み順を間違えるとうまく機能しない
  • 上から順番に読むので、途中のファイルでエラーが起こると続きが読まれない

これを解決するのがモジュールとのこと。

モジュールとは何か

では、モジュールとは何か。

※参考:https://wa3.i-3-i.info/word12243.html

モジュール (module)とは
「部品」のこと。
もう少し、いろいろ書くと
「そいつ単独でも機能としては成立するけど、普通は他のものと組み合わせて使うよ!」な部品のこと

部品ね。

1.その気になれば単独でも動かせるよ → そいつ単体でも「機能」としては成立しているよ
2.でも普通は単独では動かさないよ → 普通は何かと合体させて動かすよ
3.合体させるのは楽だよ → 合体するときの接続部分の形とかが決まってるよ

何かと合体させる前提で接続の形が決まっている部品と。

ES-Modules

JSのモジュールは「ES-Modules」というらしい。ESはECMAScriptだね。

※参考:ブラウザで覚えるES Modules入門 - JavaScriptでモジュールを使う時代 - ICS MEDIA

Can I useで見ると、IE以外の主要ブラウザは対応している模様。

※参考:Can I use... Support tables for HTML5, CSS3, etc

モジュール書き出し(export)用のファイルを作成

実際にやってみよう。まず、export用のファイルを作成する。ファイル名はexport.jsとでもしておくか。

export用の処理

export function 関数名(引数) {
    //処理
}

通常の関数の前に「export」を追加する形。

実際に書いてみる。

export function aisatsu(massage) {
    alert(massage);
}

まずは簡単にアラートからw

HTML上にモジュール読み込み(import)の処理を書く

次に、HTMLファイル上でモジュールを読み込む。こんな形。

<script type="module">
    import {関数名} from "jsファイル";
    //処理
</script>

scriptタグに注目!type属性が「module」になっている!!

「import」で関数を読み込み、「from」でその関数が書かれているファイルを読み込む。

実際に書いてみる。

<script type="module">
    import {aisatsu} from "js/export.js";
    aisatsu("はじめまして、モジュール君♪");
</script>

さあどうだ!

……ん?

ありゃ?

何も起こらない。真っ白画面…。

返事がない、ただの屍のようだ。。なぜ?

おお!先ほどの参考記事にヒントがあった!

import文のfromの中では必ず./や../、/、といったパスで記述しなければなりません。xxx.jsというように記述するのはNGで、./xxx.jsとファイルパスを明確に記載します。

※参考:ブラウザで覚えるES Modules入門 - JavaScriptでモジュールを使う時代 - ICS MEDIA

要るのなら パスを書きましょう ホトトギス!

<script type="module">
    import {aisatsu} from "./js/export.js";
    aisatsu("はじめまして、モジュール君♪");
</script>

リベンジ!

f:id:idr_zz:20191108055356j:plain

やた!アラートでた!こちらこそはじめまして♪

importの詳細はこちらも参照

※参考:import - JavaScript | MDN

例えばモジュールの中身全体を読み込むにはこう書く。

<script type="module">
    import * as オブジェクト名  from "jsファイル";
    //処理 オブジェクト名.関数名 など
</script>

オブジェクト名はimport側で命名していい。この中にjsファイルの関数が入る。

モジュール内の複数の関数を読み込むにはこう書く。

<script type="module">
    import {関数名, 関数名, 関数名} from "jsファイル";
    //処理
</script>

export defaultを使って名前をimport側でつける

exportには他の書き方もあって、「export default」を使うとexport側は無名関数にして、import側で名前をつけれる。

※参考:export - JavaScript | MDN

エクスポート方法は、名前付きとデフォルトの 2 種類あります。名前付きエクスポートはモジュールごとに複数持てますが、デフォルトエクスポートは 1 つに限ります。

確かに。デフォルトエクスポートなのに中に複数のモジュールがあったらどれを読み込んだらいいかわからなそうだ。

export defaultの書き方

export default funcrion (引数) {
    //処理
}

exportの次に「default」が入って、関数は無名関数になる。

先ほどのexport.jsのaisatu関数を書き換えると…

export default function (massage) {
    alert(massage);
}

関数名がなくなった…。

この状態でブラウザをリロードしても、当然なにも起こらない。返事がないただの屍に戻る…。

デベロッパーツール も当然「SyntaxError: Importing binding name 'aisatsu' is not found.」(aisatsu関数がみつからないよ!)と言ってる。

次にimpot側を書き換える。

<script type="module">
    import aisatsu from "./js/export.js";
    aisatsu("また会えたね、モジュール君♪");
</script>

先ほどの「aisatsu」を囲っていたブロック「{ }」を取っただけ。

そうすると…

f:id:idr_zz:20191108061915j:plain

やた!モジュール君に再開でけた!!

この「aisatsu」のメソッドはexport側ではなくimport側で自由につけることができるわけだ!export側は処理を書いた無名関数があるだけ。

最後に

ということで、外部JSをファイル単位ではなくモジュール単位で読み込むimport、exportを事初めてみました。この動きがvue.jsやnuxt.jsでは多様されることになり、次回書く予定のnuxt.jsにも登場するので、先に理解できてよかった。

このモジュール読み込み関係が入り組むと複雑になってくるので、それを一体化するモジュールバンドラWebPackの登場になるようです。モジュールを体験することでだんだんwebpackの位置付けがイメージができてきた気がする。

それではまた!


※参考:ネイティブJSいろいろやってみたシリーズ

qiita.com