valid,invalid

関心を持てる事柄について

gulp-util の問題、deprecation warning と migration path について

2017年12月28日に The Problem with gulp-util という記事が公開された。

medium.com

gulp をウォッチしていたわけではないのだが、たまたま残された gulp 資産を触っている時に deprecation warning がコンソールに出力され、そのメッセージ中にこの記事へのリンクがあった。

warning gulp > gulp-util@3.0.8: gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5

記事の内容を要約すると以下のようになる。

TL;DR

  • gulp v4 リリースにあたり gulp-util はもう deprecation です
  • gulp-util はただの便利関数群なので使用している機能に応じて個別のライブラリに置き換えてください
  • 6752個ものライブラリが依存している… migration を手伝いましょう

同記事を抄訳したり加筆したりしつつ、もう少し詳細を見ていく。


A little postmortem

先週 GitHub で公開した gulp v4.0.0-alpha.3、これが破壊的変更を含むとは知っていたがどれほど広範囲に影響が及ぶかは想像していなかった。これは gulp-util に依存する6,752個のモジュールのためだ。だいたいは古くなった Vinyl を使用している*1

Why deprecation now?

gulp-util はただのモジュールの集まりなので2014年以来ずっと廃止するつもりでいた。ロギングのためだけになぜその他の無駄なモジュール、たとえば beeper もダウンロードしなければいけないのだろうか?プラグインのダウンロードサイズを大幅に増やすだけだ。皆がそれぞれ必要とする個々のモジュールを使うよう期待していたが、みな現状維持を選んでしまったらしい。

移行パスはそう複雑でないと踏んでいたが、先週の変更でこれは予想以上の大きな問題だとわかった。 古い Vinyl には互換性がないにも関わらずいまだ多くのプラグインで使用されている。 しかし Vinyl v2 は glup-util 付きではリリースされない。これは、我々がプラグインの作者たちに個々のモジュールへ移行してもらいたいからだ。

結果、gulp-util で警告を出すことにした。これは私たちが望んでいたエレガントな移行ではないのだが…。もしあなたが使用するプラグインが gulp-util に依存している場合、インストール時に deprecation 予定が通知される。修正を行うまではどのプラグインが警告を引き起こしているのかは分からない。

もし gulp-util に依存したプラグインが gutil.File API を使用していないのなら、そのプラグインは壊れていないかもしれない。 その場合は緊急ではないが、それでも gulp-util から離れるべきだ。

Help us fix the ecosystem

これらの手順でプラグイン作成者の gulp-util からの移行を助けよう。

  1. npm ls gulp-util を実行して、依存するプラグインのリストを取得する
  2. それぞれのプラグインに対して npm issue {PLUGIN NAME} を実行し、issue tracker をブラウザで開く
  3. issue をオープンするか、以下の API を置き換えて gulp-util を削除するようにした pull request を作る

※ コードの例は自分が実際に置換するときに使った方法(随時追記する、かも)

const gutil = require('gulp-util')
new gutil.File()

# should be

const Vinyl = require('vinyl')
new Vinyl()
const gutil = require('gulp-util')
gutil.replaceExtension(path, newExtention)

# should be

const replaceExt = require('replace-ext')
replaceExt(path, newExtention)
const gutil = require('gulp-util')
gutil.colors.red(message)

# should be

# Node 4 以降
const fancyLog = require('chalk')
chalk.red(message)

# Node 0.10 のような古いバージョンをサポートする場合
const colors = require('ansi-colors')
colors.red(message)
const gutil = require('gulp-util')
gutil.log(message)

# should be

const fancyLog = require('fancy-log')
fancyLog(message)
const gutil = require('gulp-util')
gutil.template(tmpl, data)

# should be

const template = require('lodash.template')
template(tmpl)(data)
const gutil = require('gulp-util')
gutil.env.production

# should be

const parseArgs = require('minimist')
const env = parseArgs(process.argv.slice(2))
env.production
const gutil = require('gulp-util')
gutil.noop()

# should be

const through = require('through2')
through.obj()
const gutil = require('gulp-util')
new gutil.PluginError()

# should be

const PluginError = require('plugin-error')
new PluginError()

(抄訳終わり)


現状

gulp-util, gulp のメンテナを中心に以下の issue でエコシステム全体のマイグレーションを進めている。

github.com

6,000個以上もあるので全てをまかなうのは無理そうだが、多く利用されているものから順次対応していくそうだ。

言い換えればコントリビューションチャンスなので自分も幾つか Pull Request を出してみた。メンテナがかなり精力的に色んなライブラリを直しているようなので、作業がバッティングしないよう issue や PR をちゃんとチェックするか、マイナーなライブラリから始めるとよさそう。まぁ、gulp 周りは死んでいるライブラリも多いのでマイナーなものだと永遠にマージされない可能性もあるが…。

github.com

github.com

*1:Vinyl は仮想ファイルオブジェクトを扱うライブラリ。ビニールと書くと聞き馴染みがある