PostCSS v4.1.0からプラグインAPIが実装され、postcss.plugin()でプラグインを作ることが推奨されるようになった。このガイドラインに従って作ることで、プラグイン間で一貫性が保たれ、エラーもわかりやすくなるというわけだ。一見良いとこずくめだが、それだけだとPostCSSプラグインの実行に常にPostCSSが必要になってしまう。Node.jsモジュールとして機能しているかというと微妙なところだ。

仮にCSSWringpostcss.plugin()だけを使って作り直されたとしてみよう。

var fs = require("fs");
var postcss = require("postcss");
var csswring = require("csswring");

var input = "main.css";
var output = "main.min.css";

postcss([
  csswring()
]).process(fs.readFileSync(input, "utf8"), {
  from: input,
  to: output
}).then(function (result) {
  fs.writeFileSync(output, result.css);
});

PostCSSプラグインなので、このようにPostCSSの使い方をちゃんと知って使わざるをえない。もちろん他のPostCSSプラグインと組み合わせることもあるので、最終的にはこういう利用に落ち着くことはありうる。しかしCSSWringの機能のみを必要とする場合にもこう書かざるをえないのは無駄が多い。Autoprefixerのようにこういった形でコアを書き、別にラッパーを提供するという手もあるが、メンテナンスの手間が倍増することは確実だ。

また必要なPostCSSのバージョンを調べて、手作業で依存を解決しなくてはならないことも欠点になる。CSSWring側のpackage.jsonですでに依存バージョンを明示していることを効果的に利用することができない。

var fs = require("fs");
var csswring = require("csswring");

var input = "main.css";
var output = "main.min.css";

var result = csswring.wring(fs.readFileSync(input, "utf8"), {
  from: input,
  to: output
});
fs.writeFileSync(output, result.css);

CSSWringではこのように標準的なNode.jsモジュールのように利用することができる。Promiseではないことを考慮しても、コードは短くなっている。そもそもとしてPostCSSプラグインとしての使い方を知らなくても、はっきり言うのならPostCSSの存在を知らなくても書けるようになっている。

またこのスクリプトのdependenciesからPostCSSが不要にもなる。つまり依存管理をモジュール側に任せることができるわけだ。


プラグイン・システムというような方向から見ると、そういうデザインだとも言えるだろう。だがあるNode.jsモジュールを使う時にその依存モジュールの使い方をも知らなくてはならないという見方をするとどうだろうか。そんなことは知らなくてもそれ単体で使えるようになっているべきではないだろうか。

プラグイン・システムのような独自の生態系がいくつかのルール付けによって守られるようになると、同時にそれを内包する生態系(ここではNode.jsとnpm)との間に囲いを築くことにもなる。その囲いが低く感じられるか高く感じられるかはなんとも言えない。深くその独自の生態系について知れば、必要な高さの囲いだと納得できるかもしれないが、万人にそれを求めるのは酷だろう。

もちろんPostCSSプラグインはまったく悪いものではないし、PostCSSのプロセッサーとしてのみ機能するモジュールを書く場合に最も良い選択であることは確かだろう。ただそれだけではなく、Node.jsモジュールとしても単体で使えるようなインターフェイスも用意しておくことで、もっと使いやすくなるはずだ。