13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AltJS製のNodeモジュールをGitHubから直接インストールすると同時に、そのライブラリのビルドを自動化するpackage.jsonの設定

Last updated at Posted at 2020-07-01

この投稿では、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 installyarn addと同時に、インストールしたモジュールのビルドを実行するにはどうしたらいいか、どういう設定をpackage.jsonに施したらいいかについて説明します。

ステップ1: モジュールのビルド方法を調べる

まず、自プロジェクトのpackage.jsonをいじる前に、ビルドするパッケージのpackage.jsonを開いて情報収集します。

例えば、@suin/is-objectパッケージのpackage.jsonは以下のようになっています:

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 addnpm install後に何かコマンドを実行するには、postinstallscriptsフィールドに追加します:

package.json
{
  "name": "my-app",
  "scripts": {
    "postinstall": "echo インストール後になにかするよ"
  }
}

CleanShot 2020-07-01 at 09.23.12@2x.png

postinstallにはシェルスクリプトが書けるので、ここにモジュールをビルドするためのコマンドを書いていきます。@suin/is-objectパッケージの例では、次のようなステップでビルドします。

  1. 成果物ファイルのindex.jsがあるか確認する。
  2. あればビルドしない。→ 終了
  3. なければ、
    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に書いておきます:

package.json
{
  "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'

実行結果は次のようになります。ライブラリのインストール後に、ライブラリのビルドが行われました:

CleanShot 2020-07-01 at 09.49.27@2x.png

以上で、package.jsonの設定は完了です。

これにより、AltJS製のNodeモジュールをGitHubから直接インストールすると同時に、そのライブラリのビルドが自動化されます。

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?