細かすぎて伝わらない package.json 小ネタ三選

こんにちは、和田 (@t_wada) です。本日は Node.js Advent Calendar の 7 日目として、 Node.js で開発する際の設定ファイル package.json にまつわる Tips について書きたいと思います。

はじめに

私はこれまで power-assert を筆頭に、いくつか npm モジュールをリリースしてきました

Node.js を使った開発には、設定ファイル package.json の記述が必要です。特に npm モジュールを公開する場合には、設定すべき事、考えるべき事もいろいろ増えてきます。今回は、 npm モジュールを作ってきた過程で学んだ package.json に関する Tips の中で、あまり知られていないマイナー気味なものを挙げていきたいと思います。

Tips1: package.json の files フィールドでホワイトリスト

開発には必要なものの、配布する npm には含めたくないディレクトリやファイルがあると思います。例えば .idea ディレクトリや .vimrc.project のようなのような開発環境固有の設定ファイル群が挙げられるでしょう。このようなファイル達が配布モジュールに混入してしまうのを避けるため、従来では .npmignore というファイルに npm から除外したいファイルパターンを記述していました。例えば、次のように書かれます。

.git*
.idea*
/bower_components

この .npmignore は、言うなればブラックリストです。ブラックリストであるということは、未知のファイルに対して無防備になりがちである、ということも意味しています。例えば上記 .npmignore は IDEA 派の人のファイルのようですが、この人が vim 派に乗り換えて .vimrc.project.gitignore に追加したものの、 .npmignore には追加を忘れたままリリースすると、 .vimrc.project の入った npm モジュールのできあがりです。エディタの設定くらいなら良いかもしれませんが、もっとプライベートな内容が書かれているファイルだったらどうでしょう。

やはりブラックリストだけでは危ういのです。足りないのはホワイトリスト、つまり配布するファイルだけを記述できる方法です。そこで登場するのが package.json に記述する files フィールドです。

package.json の files フィールドは、配布する npm モジュールに含めるべきファイルやディレクトリを記述するフィールドで、まさにホワイトリストとして機能します。具体的には npm モジュールに含めるファイル名やディレクトリ名を記述します。

  "files": [
    "README.md",
    "index.js",
    "package.json",
    "lib",
    "test"
  ],

上記のように書くと、 README.md, index.js, package.json ファイル、及び lib,test ディレクトリ配下が配布 npm に含まれるようになり、他のファイルは除外されます。

package.json の files フィールドは .npmignore ファイルと組み合わせることもできます。例えば上記設定で test ディレクトリ内に配布物からは除外したいファイルがいくつかある場合は、そのファイル達を除外するパターンを .npmignore に書けば、ホワイトリストとブラックリストのコンボ完成です。基本的に files フィールドにホワイトリストを書き、その中から個別に除外したいパターンがあれば .npmignore に書く、という組み合わせが良いのではないかと思います。

(追記: package.json の files はホワイトリストですので、 npm に含まれるべき新規ファイルを作成した際に files に追加を忘れると、そのファイルは配布する npm から漏れることになってしまいます。ご注意ください)

Tips2: package.json のフィールド並び順に悩むくらいなら fixpack

npm モジュールの開発が進んでくると、 package.json ファイルの中身がだんだん大きくなってきます。

開発初期は name, version, description, keywords, main, scripts, author, license などのフィールドだけだった package.json に、 dependencies, devDependencies のような依存モジュール定義や、 bugs, homepage, repository といった URL の定義、そしてもちろん files フィールドが加わっていきます。さらに package.json には browserify 関係のフィールドやフロントエンド関係のフィールドなどを、ある程度自由に定義して追加できるという(良い意味での)自由さがあります。

複数のプロジェクトを開発していると、これらフィールドの並び順などがプロジェクトによってバラバラになってきて整理が難しくなったり、簡単にコピーできなくなってしまい、だんだんと混沌状態になってきます。 package.json の規約や、フィールドの並びの基準が欲しくなってくるところです。

そこで登場するのが fixpack です。このツールは package.json の中身を

  • name が一番最初
  • description が二番目
  • version が三番目
  • author が 四番目
  • 残りのフィールドをアルファベット順

に並べ替えてくれます。さらに dependenciesdevDependencies の中身もアルファベット順に並び替えてくれます(これは npm install --save 等でもできますが)。

fixpack を使えば package.json 内の並びを悩まなくとも良くなります。 fixpack コマンドを使うだけです。

ちなみに bower.json に対して同様のことを行う fixbow もあります。(私の PR は放置されてしまっていますが……)

Tips3: ライセンス、 MIT で良いなら mit-license.org

OSS 開発においてライセンスが大事なことは言うまでもありません。 npm の世界では Permissive な MIT ライセンスが一般的です。私も MIT 以外にする強い理由は無いので、 npm モジュールに関しては MIT ライセンスで公開しています。

他のライセンスと同様、 MIT ライセンスもライセンスの明記が必要です。 opensource.org の The MIT License の全文をコピペして "year" と "copyright holders" を置き換えて……少しの手間なのですが、手間は手間です。毎回ほぼ同じなのに……ということで一度作ったライセンスファイルをコピーして使い回すのですが、そうすると内容がほぼ同じファイルがプロジェクト毎に作られることになります。もうちょっと手数を減らせないかな、というところで見つけたのが mit-license.org です。

mit-license.org は登録制の Web サービスで、登録すると新たなサブドメインが作成され、自分を権利者とした MIT ライセンス条項本文を示すパーマリンクができあがります。詳しくは remy/mit-licensemit-license.org - Weblog - Hail2u.net を読んでみてください。

登録の仕方はいくつかありますが、私はこんな感じで curl で登録しました。

$ curl -d'{ "copyright": "Takuto Wada", "url": "https://github.com/twada" }' http://twada.mit-license.org
>>> MIT license page created: http://twada.mit-license.org
$ 

これで、 http://twada.mit-license.org/ という URL で自分の MIT ライセンス条項本文にアクセスできるようになります。あとは package.json の license フィールドに URL を書けば OK です。モジュール開発が更に一手減りました。

  "license": {
    "type": "MIT",
    "url": "http://twada.mit-license.org/"
  },

ちなみに URL に年や期間を与えることもできます。 RESTful な URL 設計でとても良いですね。

おわりに

ここまで package.json に関わる Tips を三つ書いてきました。 npm はモジュール利用者にも作成者にも使いやすい、良くできたパッケージ管理システムであると感じます。特にモジュール公開の容易さは特筆すべき点であると言えるでしょう。 Node.js のエコシステムの豊穣さは、モジュール利用者からモジュール作成者に進むためのハードルが低いことで成り立っています。このエントリを読んだ皆さんも、ぜひ npm author になってみてください。そのハードルを越えるのは、意外と難しくありません。

Node.js Advent Calendar、 明日は @kjirou さんです。