今回も文章量に対して大変地味なエントリーです!
一つのリポジトリ内にあるディレクトリで別々に sass をコンパイルしなければならないプロジェクトがあり、ディレクトリごとにコンパイルするためのパッケージをインストールするのは管理面でも避けたかったので、root に共通でパッケージをインストールして各ディレクトリ内でそれぞれの npm-script を実行したかったのメモ。
文章にすると分かりづらい…
ディレクトリ構成
/root |- .git |- /node_modules |- package.json |- /src |- /projects |- /theme-a | |- /styles |- /theme-b | |- /styles |- /theme-c | |- /styles |- /theme-d | |- /styles
root にある package.json にそれぞれのディレクトリ用の npm-script を作成する
今回は sass と postCSS を使用している想定です。
/package.json
{ "name": "MyProject", "scripts": { // build の設定 "sass": "sass /src/projects/${THEME}/styles:/src/projects/${THEME}/css --no-source-map", "postcss": "postcss /src/projects/${THEME}/css/style.css -o /src/projects/${THEME}/style.min.css", // theme-a 用の設定 "build:css:themeA": "THEME=theme-a npm-run-all -s sass postcss", "dev:css:themeA": "THEME=theme-a npm-run-all -p \"sass -- --watch\" \"postcss -- --watch\"", // theme-b 用の設定 "build:css:themeB": "THEME=theme-b npm-run-all -s sass postcss", "dev:css:themeB": "THEME=theme-b npm-run-all -p \"sass -- --watch\" \"postcss -- --watch\"", // theme-c 用の設定 // theme-d 用の設定 } }
テーマがたくさんあるので、sass, PostCSS のコマンドはテーマ部分を変数で指定できるようにしました。
これが一番シンプルですが、root から実行する時にコマンドが長くなるのが難点です。
それぞれのテーマディレクトリでコマンドを実行したい
npm コマンドを実行する時、今いるディレクトリより上にある階層の package.json
を探しに行って実行するので、各テーマ内に package.json
だけ作ってしまえばうまくいくのではないかと思いました。
package.json
と node_modules が同階層にないと上手く行かない
theme-a 内に package.json
を作成しました。
/root |- .git |- /node_modules |- package.json |- /src |- /projects |- /theme-a | |- package.json <- 作成 | |- /styles
/src/projects/theme-a/package.json
{ "name": "ThemeA", "scripts": { "sass": "sass styles:css --no-source-map", "postcss": "postcss css/style.css -o css/style.min.css", "build:css": "npm-run-all -s sass postcss", "dev:css": "npm-run-all -p \"sass -- --watch\" \"postcss -- --watch\"" } }
これで実行しても上手く動作しません。
$ cd /src/projects/theme-a/ $ npm run build:css > npm-run-all -s sass postcss sh: npm-run-all: command not found npm ERR! code ELIFECYCLE npm ERR! syscall spawn npm ERR! file sh npm ERR! errno ENOENT npm ERR! ThemeA@build:css: `npm-run-all -s sass postcss` npm ERR! spawn ENOENT npm ERR! npm ERR! Failed at the ThemeA@ build:css script.
どうやら package.json
は同階層にある node_modules を探しに行くようです。
root にある package.json のスクリプトを実行するようにすればOK
npm-script は shell のエイリアスらしいので、root の package.json
がある所まで移動して、root の npm-script を実行するようにすれば、子階層にある package.json
内にある npm スクリプトから root の npm-script を実行できるようになります。 (日本語むつかしい…)
/src/projects/theme-a/package.json
を下記のように変更すればOK
{ "name": "ThemeA", "scripts": { "build:css": "cd ../../../ && npm run build:css:themeA", "dev:css": "cd ../../../ && npm run dev:css:themeA" } }
cd
で root まで移動して、/root/package.json
のコマンドを実行するようにしています。
👇 実行
$ cd /src/projects/theme-a/ $ npm run build:css > ThemeA@ build:css > cd ../../../ && npm run build:css:themeA > MyProject@build:css:themeA > THEME=theme-a npm-run-all -s sass postcss > …
開発したいテーマの階層にいる状態で root にインストールした node_modules を使った npm-script が実行できるようになりました!
₍ ᐢ. ̫ .ᐢ ₎ yattaze!!
root のパスをいい感じに取得したい
子階層から npm-script でコマンドが実行できるようになったのですが、root のディレクトリの指定方法があまりイケてません。
今後運用の関係で構造が変更になったり階層が異なる場所から実行しなければならないようなケースが出てくるとパス指定を考えるのが面倒です。
git rev-parse を使ってプロジェクトのルートディレクトリを取得する
プロジェクトが git 管理されているなら git rev-parse --show-toplevel
というコマンドを使ってプロジェクトのルートが取得できるので、これを利用して root の package.json
があるディレクトリを取得すると良さそうです!
/src/projects/theme-a/package.json
を下記のように変更します
{ "name": "ThemeA", "scripts": { - "build:css": "cd ../../../ && npm run build:css:themeA", + "build:css": "cd ${git rev-parse --show-toplevel} && npm run build:css:themeA", - "dev:css": "cd ../../../ && npm run dev:css:themeA" + "dev:css": "cd ${git rev-parse --show-toplevel} && npm run dev:css:themeA" } }
₍ ᐢ. ̫ .ᐢ ₎ いい感じになった!
所管
npm 使ったプロジェクトはどの階層にいても上の階層にある package.json
のコマンドが使えていたので、package.json
を子階層に作っても上の階層にある node_modules のパッケージを使えるのだと思っていたのですが、package.json
があると同階層の node_modules ディレクトトリからパッケージを探しに行くのだと知れてよかったです。
それと、 npm-script に変数を渡す方法も少し詳しくなれました!
git rev-parse
コマンドは全然知らなかったので、また詳しく調べてみようと思います。
ちょっとした事をしたいだけだったのですが、結構盛大にハマってしまいました。
ハマった分だけ強くなれる!ゴゴゴゴゴ…
[参考]
- javascript - Pass command line variable into npm script? - Stack Overflow
- Is it possible to use npm to run scripts in multiple subfolders? - Stack Overflow
- OSに依存しない npm-script の書き方 - Qiita
- git rev-parseを使いこなす - Qiita
- 今まで知らずにいたnpmスクリプトでできる3つのこと
- Node.jsユーザーなら押さえておきたいnpm-scriptsのタスク実行方法まとめ - ICS MEDIA
- npm-scriptsでdart-sass → postcssのタスクを作る。(ディレクトリ指定 & watch)