Edited at

nodejs, ES6 で dependency injection with awilix

More than 1 year has passed since last update.


概要

nodejs でちょっとしたアプリ(WebAPI や DB からデータを取得して、AWS S3に登録する)を作ることになりました。

小さなコードなので、typescript とか使うのも面倒だなと思い、ES6 で書いていました。

プロトタイプ的に一通り実装したあと、プロダクト用に仕上げるに当たって、やはり DI 必要だなと思い、調べていたところ、awilix が使いやすかったという話です。


そもそも何で DI が必要か

プロトタイプでは DAO を以下のように実装していました。


dao.js

const webDAO = require("./net"); // WEB API 通信モジュール

const dbDAO = require("./db"); // DB 操作モジュール
const s3 = require("./s3"); // S3 操作モジュール

module.exports = {
getData1: function(code){
return webDAO.getData(code);
},
getData2: function(type){
return dbDAO.getData(type);
},
putData: function(key, data){
return s3.putObject(key, data);
}
};


使う側は以下のような感じです。


userSide.js

const dao = require("./dao");

const data1 = dao.getData1("sample");
dao.putData("sampleKey", data1);


で、これだと困ることがいくつかあります。


  • ローカル環境では S3 じゃなくてファイルに出力したいこともある

  • ローカル環境ではデータを固定にしたいこともある

  • 一連の処理のテストコードを書きたいが、外部リソースに依存していては・・・

と言うわけで DI の出番です。


Awilix が良いと思った理由

JS の DI framework って決定版的なものがないですよね、きっと。

以前に typescript を使った時は inversifyJS を使ったのですが、JS対応はイマイチだったので、他を探していたところ、Awilixを見つけました。

シンプルで使い勝手が良さそうです。ES6 の Proxy を使っているらしいです。


DI 版に修正する

※サンプルなので諸々テキトーです。

DI なので dao をコンストラクタで受け取るようにします。

const awilix = require('awilix');

const container = awilix.createContainer();

// モックの DAO
function mock() {
const fs = require("fs-extra");
container.registerValue({
dao: {
getData1: function(code){
return [];
},
getData2: function(type){
return [];
},
putData: function(key, data){
return fs.outputFile(`${key}.txt`, data);
}
}
});
}

// プロダクト用の DAO
function prod() {
const dao = require("./dao/dao");
container.registerValue({dao: dao});
}

mock(); // 注:ここを環境によって切り替える。
// prod();

// 以下、使う側

class TestUser {
constructor(opts) {
this.dao = opts.dao; // モックまたはプロダクト用の DAO がインジェクトされる
}

test() {
this.dao.getData1("sample");
}
}

container.registerClass({
testUser: TestUser
});

const testUser = container.resolve("testUser");
testUser.test();

サンプルなので諸々テキトーです。

Usageが分かりやすいので、そちらを参照してください。


まとめ

Awilix で testable な nodejs 開発をしましょー。