Old Sunset Days

Node.jsでES6形式のモジュールimportを利用する

日付 タグ node.js カテゴリ node.js

目次

CommonJS形式とES6(ES2015)形式でのモジュール扱いの違い

Node.jsの勉強でサンプル等を見ていると、requireでモジュールを取り入れているものと、import文で取り入れているものがあって、最初は?となったが、importで取り入れられる形式はES6(ES2015)で追加された仕様とのこと。

JavaScriptの場合は、IEがES5までしか対応していなかったりするので、importがChromeやFirefoxでは利用できるが、IEで動かないという心配があるようだが、Node.jsを使っている限りにおいてはNode.jsの最新バージョンを利用しているのであれば問題ない。

Node.js 13.2以前ではオプションフラグでexperimental-module的扱いだったが、以降のバージョンでは普通に使えるようになっているようだ。 そうであるなら、今後はどちらかというとimportを積極的に利用していった方がいいのかもしれない。

そこで今回はCommonJSでのモジュールとES6(ES2015)でのモジュールの違いをちょっと見ていく。

CommmonJSでのモジュール

まずは良くサンプルで目にする機会の多いCommonJSでのモジュール

外部に公開するモジュールの関数は

exports.functionName = function(arg){...};

あるいは

module.exports.functionName = function(arg){...};

で定義する。 上記はどちらも同じ意味になる。

例えば、

commonjs_module.js

var count = 0;
const externalval = 10;
exports.externalval = externalval;
exports.increment = function() { return ++count; };
exports.check = function() { return `count = ${count}`; };

こんな感じでincrementhello、およびexternalvalを外部に公開したとしよう。これを利用する

commonjs_test.js

const import_mod = require('./commonjs_module');

// 公開されている関数へのアクセス
import_mod.increment();
console.log(import_mod.check());

import_mod.increment();
console.log(import_mod.check());

import_mod.increment();
console.log(import_mod.check());

// 公開されていない変数へのアクセス
console.log('checking variable ...');
console.log(import_mod.count);

// 公開されている変数へのアクセス
console.log('checking variable ...');
console.log(import_mod.externalval);

を用意して、これを実行してみる。

$ node commonjs_test.js
count = 1
count = 2
count = 3
checking variable ...
undefined
checking variable ...
10

incrementcheckはcommonjs_module.jsから公開されているのでこれを外部から呼び出し、countという変数がインクリメントされていく様子が確認できる。

変数countは公開されていないので、それを外部から直接見ようとするとundefined状態になる。

一方、externalvalは公開しているので、こちらは外部からも見ることが可能になっている。

このように変数が勝手に外からのぞかれたり、変更されないようにして必要な処理や変数だけを外部に公開することが可能なのがモジュール化で、CommonJS形式での書き方は以上の通り。

ES6(ES2015)でのモジュール

ではES6(ES2015)形式でのモジュールの書き方はどうか?

今回はES6(ES2015)形式を明示的に示すため、.mjsという拡張子で以下のファイルを用意

es6_module.mjs(関数リテラル)

var count = 0;
export const externalval = 10;
export const increment = function() { return ++count; };
export const check = function() { return `count = ${count}`; };

以上のモジュールを用意した上で、テスト用のコードを用意する。

es6_test.mjs

import * as import_mod from './es6_module.mjs';

// 公開されている関数へのアクセス
import_mod.increment();
console.log(import_mod.check());

import_mod.increment();
console.log(import_mod.check());

import_mod.increment();
console.log(import_mod.check());

// 公開されていない変数へのアクセス
console.log('checking variable ...');
console.log(import_mod.count);

// 公開されている変数へのアクセス
console.log('checking variable ...');
console.log(import_mod.externalval);;

これを実行すると、

$ node es6_test.mjs
count = 1
count = 2
count = 3
checking variable ...
undefined
checking variable ...
10

CommonJS形式でやった時と同じ結果が得られた。

なお、es6_module.mjsは関数リテラルを使っているが、通常のfunction文を使って、

es6_module.mjs(function文)

var count = 0;
export const externalval = 10;
export function increment() { return ++count; };
export function check() { return `count = ${count}`; };

としても同じ動作結果が得られる。

今の例では、

import * as import_mod from './es6_module.mjs';

でexportされているものを全て読み込んだが、必要なものだけを読み込むことも可能だ

import {increment as increment, check as check, externalval as externalval} from './es6_module.mjs';

のように個別にimportをすることも可能。

その場合は、

import_mod.increment();

としていたのは

increment();

に変える必要がある。

以上、CommonJS形式とES6(ES2015)形式でのモジュール読み込みの仕方の違いを見てきた。
今後はES6(ES2015)形式でのモジュール読み込みもどんどん使っていきたい。