概要
Node.js、ES6、Typescriptを一気に調べていたせいで、いろいろなパターンのモジュール読み込み方法に出くわして、ちょっと混乱したので、整理しました。
Node.jsのモジュール読み込み
Node.jsのモジュール読み込みは以下のような形になります。
// node/myModule.js class myModule { constructor() { console.log('Hello, I am a module'); } hello() { console.log('hello!'); } goodbye() { console.log('goodbye!'); } } function test() { console.log("hoge"); }; //// test関数とmyModuleクラスをエクスポート module.exports.test = test; module.exports.myModule = myModule;
// node/main.js //// モジュール読み込み var mod = require('./myModule'); mod.test(); var m = new mod.myModule(); m.hello();
Node.jsは module.exports
でエクスポートを行い、
require
で読み込みを行います。
Node.jsの形式なので、そのままNode.jsで実行できます。
$ node node/main.js hoge Hello, I am a module hello!
ES6(ECMAScript2015)のモジュール読み込み
ES6のモジュール読み込みは以下のような形になります。
// es6/myModule.js export class myModule { constructor() { console.log('Hello, I am a module'); } hello() { console.log('hello!'); } goodbye() { console.log('goodbye"'); } } export function test() { console.log('hoge'); }
// es6/main.js import {myModule,test} from './myModule'; test(); var m = new myModule(); m.hello();
ES6では、export
をクラス定義や関数定義の前に付けてエクスポートを行い、import
で読み込みを行います。
このままでは、Node.jsで実行することができません。
$ node es6/main.js es6/main.js:1 (function (exports, require, module, __filename, __dirname) { import {myModule,test} from './myModule'; ^^^^^^ SyntaxError: Unexpected token import at createScript (vm.js:80:10) at Object.runInThisContext (vm.js:139:10) at Module._compile (module.js:599:28) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Function.Module.runMain (module.js:676:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3
ES6からES5に変換してくれるBabelを使うと以下のようなソースコードになります。
$ babel es6/myModule.js 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.test = test; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var myModule = exports.myModule = function () { function myModule() { _classCallCheck(this, myModule); console.log('Hello, I am a module'); } _createClass(myModule, [{ key: 'hello', value: function hello() { console.log('hello!'); } }, { key: 'goodbye', value: function goodbye() { console.log('goodbye"'); } }]); return myModule; }(); function test() { console.log('hoge'); }
$ babel es6/main.js 'use strict'; var _myModule = require('./myModule'); (0, _myModule.test)(); var m = new _myModule.myModule(); m.hello();
Node.jsのmodule.exports/require
形式に変換されていますね。
Typescriptのモジュール読み込み
Typescriptでは3パターンの方法が用意されています。
ES6と同じexport/import
Typescriptでは、ES6と同じ形式でモジュールの読み込みをサポートしています。 ほぼ同じなのでソースは省略します。
export =
とimport = require()
また、以下のような形式もサポートしています。
// ts/myModule.ts class myModule { constructor() { console.log('Hello, I am a module'); } hello() { console.log('hello!'); } goodbye() { console.log('goodbye!'); } } function test() { console.log('hoge'); } export = {myModule, test};
// ts/main.ts import mod = require("./myModule"); mod.test(); var m = new mod.myModule(); m.hello();
/// reference path
読み込むソース(例ではmain.ts)で、/// <reference path="{ファイルパス}" />
を記述する方法です。
この方法を使っていると、読み込まれる側(例ではmyModule.ts)では、exportなどの記述は不要になります。
// ts/myModule.ts class myModule { constructor() { console.log('Hello, I am a module'); } hello() { console.log('hello!'); } goodbye() { console.log('goodbye!'); } } function test() { console.log('hoge'); }
// ts/main.ts /// <reference path="./myModule.ts" /> //import mod = require("./myModule"); test(); var m = new myModule(); m.hello();
まとめ
Node.js、ES6、Typescriptでそれぞれモジュールの読み込みの方式が定義されていて、ややこしかったので、まとめてみました。特にES6の方式で記述しているソースをNode.jsで実行しようとしてエラーが出てしまって、よく分かってませんでした。
まだまだいろいろな書き方はあると思いますが、今回は基本的なことだけにとどめました。