Node.js で ES Modules 記法を動かしてみる

ブラウザ上で JS を import するための仕組みとして、ES Modules という仕組みができた。コレを Node.js 上でも動かせるということで、やってみた。

目次

前提条件

ES Modules を試すには、Node.js v12 以降が必要。今回は以下の環境で試してみた。

$ node -v
v12.16.1

$ npm -v
6.13.4

ES Modules を有効にするための条件がある

Node.js 上で ES Modules を有効にするためには、いくつかの条件がある。

必須:import 文にファイル拡張子を必ず書く

ES Modules では import from 構文が使えるようになるが、拡張子の指定が必須である。

// example.mjs があったとして…

// ↓ コレは拡張子がないので NG
import example from './example';

// ↓ このように拡張子込みで書く
import example from './example.mjs';

必須:実行時に --experimental-modules フラグを付ける

$ node index.mjs のように実行しようとしても、ES Modules として解釈されない。

$ node --experimental-modules index.mjs

このようにオプションを入れる必要がある。オプションはファイル名より手前に入れないとダメらしい。

ソースファイルの拡張子を .mjs にする場合

ソースファイルの拡張子を .js ではなく .mjs とする場合は、上の2つを対応すれば OK。

import hello from './hello.mjs';
hello();
export default function hello() {
  console.log('Hello');
}
$ node --experimental-modules mjs/index.mjs 
(node:50565) ExperimentalWarning: The ESM module loader is experimental.
Hello

package.json は別になくても動く。

ソースファイルの拡張子を .js にする場合:さらに条件がある

少しつまづいたのが、ソースファイルの拡張子が .js のままな場合に、ES Modules を有効にする方法。

先ほどとほぼ同じコードで、import 部分の拡張子が .js になっているパターンを用意する。

import hello from './hello.js';
hello();
export default function hello() {
  console.log('Hello');
}

package.json は用意せず、次のように実行してみると、エラーが出てしまう。

$ node --experimental-modules js/index.js 
(node:50599) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
/Users/Neo/practice-esm/js/index.js:1
import hello from './hello.js';
^^^^^^

SyntaxError: Cannot use import statement outside a module

コレを回避するには、package.json を用意し、"type": "module" 指定を加える必要がある。最低限以下でも動く。

$ echo '{ "type": "module" }' > package.json

$ node --experimental-modules js/index.js 
(node:50651) ExperimentalWarning: The ESM module loader is experimental.
Hello

以上

Node.js 上で ES Modules を動かすのはまだまだ大変だなぁ…。コレもまだ「とりあえず動かせた」レベルだし…。