JavaScriptのモジュール

 
Web Tips.
Booskanium's
Booskanium's Web Tips.

モジュール概要

JavaScriptを利用するなら汎用機能をモジュール化すると、プログラミングを行えば行っただけ効率がアップして行きます。
参考文献:JavaScript モジュール / モジュール, 導入

モジュールを使う利点

小さな部品をして扱える

モジュールで小さな部品化できるので、機能毎に保守がしやすくなる。
モジュール単位をどの様に分ければ良いかはある程度の経験値が必要かもしれません。これはオブジェクト指向プログラミングで、クラス単位を決めることと同様です。

moduleはexportとimportで

作成したmoduleはexportを記述して、利用する箇所でimportします。

importを行うJavaScriptの記述を読み込むHTMLのscriptタグにはtype="module"を指定します。
このタイプはHTMLの読み込みと準備ができたあとに有効化されます。よってHTMLの最後に書かなくても問題ありません。
しかしバンドルして利用するのならmoduleでは無い状態にトランスパイルされますので、このscriptを読み込むscriptタグはHTMLの最後に書くのが適切です。

利点は欠点、でもバンドルすれば欠点では無い。

小さなmoduleはメンテナンス性が良い、しかし沢山のモジュールファイルのimportは読み込みオーバーヘッドが大きくなります。
しかし、実務ではWebpack等でバンドルしますので欠点ではありません。

exportとimportの例

モジュールがclass構文

export対象となるロジックはclass構文(Prottypeの糖衣構文)です。モジュールはclass構文で書くのが無難です。

export

exportモジュールをgreetings.jsに以下の通り記述

export class Greetings {
	constructor() {
	}
	action(name) {
		alert(`Nice to meet you. Mr. ${name}.`);
	}
	reaction(name) {
		alert(`Nice to meet YOU too, Mr. ${user}.`);
	}
}

import

exportをimportするJavaScriptファイルをindex.jsとするなら、HTMLで

<script src="./index.js" tyle="module"></script>
「type="module"」を忘れずに。

importしているコード

import {Greetings} from './greetings.js';
const greetings = new Greetings();
greetings.action('Williams'); // Nice to meet you. Mr. Williams.
greetings.reaction('Jones'); // Nice to meet YOU too. Mr. Jones.
です。

モジュールがfunction構文

export対象となるロジックをfunctionで書く場合です。

export

greetings.jsで以下の記述

export function action(user) {
  alert(`Nice to meet you. Mr.${user}.`);
}
export function reaction(user) {
  alert(`Nice to meet YOU too. Mr.${user}.`);
}

import

exportをimportするJavaScriptファイルをindex.jsとするなら、HTMLで

<script src="./index.js" tyle="module"></script>
「type="module"」を忘れずに。

exportしたfunctionを個別にimportするなら

import {action, reaction} from './greetings.js';
action('Williams');
reaction('Jones');
です。

exportしたfunctionを全部別名でimportするなら

import * as greet from './greetings.js';
greet.action('Williams');
greet.reaction('Jones');
です。これはmodule内の一部のexportのみを利用する場合は避けたい記述です。なぜならWebpackでバンドルする時に不要な部分をカットしてもらえないからです。

まとめ

ecxport記述の色々

宣言の前に書く

export [default] class|function|variable ~
default記述はモジュールの中で一つだけ

スタンドアロン記述

export {x [as y], ・・・};

再エクスポート

export {x [as y], ...} from "モジュール.js"
export * from "モジュール.js" ※デフォルトは再エクスポートされない
export {default [as y]} from "モジュール.js" ※デフォルトの再エクスポート

import

モジュールから名前付きインポート:

import {x [as y], ...} from "モジュール.js"

デフォルト インポート:

import x from "モジュール.js"
import {default as x} from "モジュール.js"
すべてインポート:

import * as obj from "モジュール.js"

import/exportを記述する位置

コードの前後に置くことができる。

import/exportはコードの前後に置くことができる。

~コード~
export {x [as y], ・・・};
または
eexport {x [as y], ・・・};
~コード~
コードの前後どちらでも可だが、exportなら後ろ、インポートなら前に書くのが慣例

import/exportは {}の中には書けない。

以下の記述はNG

if (condition) {
	import {action} from "モジュール.js";
}

default export

記述

classa.jsの記述例

excport default class ClassA() {	//defaultはモジュールファイル中に一つなのでclassは省略可
  ~処理記述~;
}
または
class ClassA() {
  ~処理記述~;
}
export {ClassA as default};
defalutの留意事項:
・defalutはモジュールファイル中に一つだけ。複数指定は不可。
・モジュールファイル名はdefaultと同じファイル名(先頭小文字)にするのが慣例となっている。

上記のimport

import {default as ClassA} from './classa.js'
または
import * as mod from './classa.js'
mod.action('Williams');
mod.reaction('Jones');