この投稿では、NodeモジュールをGitHubから直接インストールする際、そのライブラリをインストールのタイミングでビルドする方法を紹介します。
この手法はどういうときに使うか?
普段、yarn add ライブラリ名
をすると、npmjs.orgのレジストリにアップロードされたモジュールが、手元のnode_modulesに入ってきます。仮に、ライブラリのソースコードがTypeScriptやBebelなどのAltJSであったとしても、node_modulesにインストールされるのは普通ビルド後のJavaScriptです。これはライブラリ開発者がnpmjs.orgに公開するとき、AltJSからJavaScriptにビルドしたものをアップロードしてくれているからです。
なので、モジュール利用者は、ライブラリのソースコードがもともとどんな言語で書かれているかを気にする必要がありませんし、ましてや、モジュール利用者がnpm install
しするたびに、わざわざライブラリのソースコードからビルドする必要は普通ありません。
どうしてもソースコードからインストール&ビルドしたい場合に使う
しかし、場合によっては「普通」じゃないインストールをしたい場合があります。どうしてもソースコードからインストールする必要がある場合です。
例えば、「ライブラリのGitHubにプルリクエストを送って取り込まれたけれど、npmjs.orgには未公開。でも、すぐにそのリビジョンのコードを使いたい」といったケースです。
このケースでは、どこにもビルド済みのコードがなく、TypeScriptやBebelなどのAltJSのコードがGitHub上にあるだけ、という状況になります。
YarnやNPMでは、GitHubのURLを指定してmasterブランチをnode_modulesにインストールすることができます:
npm install 'https://github.com/suin/isObject.js.git#master'
# or
yarn add 'https://github.com/suin/isObject.js.git#master'
しかし、この方法ではAltJSのコードしかインストールされず、必要となるビルド後のJSファイルが手に入りません:
ls -a1 node_modules/@suin/is-object
CHANGELOG.md
index.ts # TypeScriptしかない!
LICENSE
package.json
このままでは、モジュールをimport
/require()
しても使えません。
モジュールのインストールと同時にビルドを実行する必要があるのです。
モジュールインストール時にビルドを実行するためのpackage.jsonの設定
では、npm install
やyarn add
と同時に、インストールしたモジュールのビルドを実行するにはどうしたらいいか、どういう設定をpackage.jsonに施したらいいかについて説明します。
ステップ1: モジュールのビルド方法を調べる
まず、自プロジェクトのpackage.jsonをいじる前に、ビルドするパッケージのpackage.jsonを開いて情報収集します。
例えば、@suin/is-object
パッケージのpackage.jsonは以下のようになっています:
{
"name": "@suin/is-object",
"version": "1.1.3",
"description": "TypeScript friendly isObject function",
...
"main": "index.js",
...
"scripts": {
"build": "tsc",
...
},
"devDependencies": {
...
}
}
この中で注目するのは、main
フィールドとscripts
フィールドです。
1つ目のmain
フィールドはビルド後の成果物のファイル名です。ライブラリ利用者の我々としては、これが欲しいのでこのファイル名をメモしておきます。
2つ目のscripts
フィールドには、たいていビルドするためのコマンドが定義されています。多くの場合、build
という名前で定義することが多いです。ここはライブラリの開発者次第なので、よく調べてみる必要があります。ライブラリによってはREADME.mdやCONTRIBUTING.mdにビルドの手順が書いてあるかもしれないので、そこも目を通しておきます。この@suin/is-object
パッケージの例では、build
コマンドだけで良いことがわかります。
また、パッケージがYarnとNPMどちらでビルドしているのかも調べておきます。これは、yarn.lockとpackage-lock.jsonどちらがあるかで判断できます。
ステップ2: postinstall
にビルドのスクリプトを組む
上の調査で、ビルド後の成果物ファイル名とビルド方法が分かったら、自プロジェクトのpackage.json
に手を加えて、モジュールのインストール時にビルドを実行するように設定します。
yarn add
やnpm install
後に何かコマンドを実行するには、postinstall
をscripts
フィールドに追加します:
{
"name": "my-app",
"scripts": {
"postinstall": "echo インストール後になにかするよ"
}
}
postinstall
にはシェルスクリプトが書けるので、ここにモジュールをビルドするためのコマンドを書いていきます。@suin/is-object
パッケージの例では、次のようなステップでビルドします。
- 成果物ファイルの
index.js
があるか確認する。 - あればビルドしない。→ 終了
- なければ、
4. モジュールが依存するパッケージをインストールする。
5. モジュールをビルドする。 → 終了
これをシェルスクリプトに起こすと、次のようになります:
set -eux
# 成果物ファイルの`index.js`があるか確認する。
if [ ! -f ./node_modules/@suin/is-object/index.js ]
then # なければ、
cd ./node_modules/@suin/is-object
# モジュールが依存するパッケージをインストールする。
yarn install --frozen-lockfile
# モジュールをビルドする。
yarn build
fi
このシェルスクリプトをpostinstall
に書いておきます:
{
"scripts": {
"postinstall": "set -eux; if [ ! -f ./node_modules/@suin/is-object/index.js ]; then cd ./node_modules/@suin/is-object; yarn install --frozen-lockfile; yarn build; fi"
}
この状態で、モジュールをGitHubからインストールしてみます:
yarn add 'https://github.com/suin/isObject.js.git#master'
実行結果は次のようになります。ライブラリのインストール後に、ライブラリのビルドが行われました:
以上で、package.jsonの設定は完了です。
これにより、AltJS製のNodeモジュールをGitHubから直接インストールすると同時に、そのライブラリのビルドが自動化されます。