読者です 読者をやめる 読者になる 読者になる

ゆとり世代プログラマの備忘録

ゆとり世代プログラマが備忘録を書いていく

Visual Studio Code でpackage.jsonが複数ある場合に各scriptsの内容をタスクランナーから実行する方法

何がしたいのか

package.jsonがカレントディレクトリになく、 且つ package.jsonが複数のサブディレクトリにまたがって複数存在する場合に、 VSCodeのタスクランナーからそれぞれのpackage.jsonの scripts に指定されているscriptを実行したい!!!!

したい!!!

どうしてそう思った

Webのフロントもサーバーも両方TypeScriptで書いていて、 フロントとサーバーを別々のフォルダで管理して、pacakge.jsonもそれぞれ別々に用意していると、 以下のようなフォルダ構成なることが考えられる。

というか、なった!

こういう構成にするのが馬鹿だって石投げつけられたら、もうそのまま石投げつけられますが!

root/   ←ここから VSCode で開いている
    │
    ├ client/  ← フロントエンド用プロジェクト Angular2とかやる方
    │    ├ index.ts
    │    ├ webpack.config.json
    │    │ ...etc
    │    └ package.json ← フロントエンド用の packatge.json こっちにフロントのビルド用scriptが書いてある
    │    
    └ server/ ← バックエンド用プロジェクト Express 使ってAPI作る
         ├ app.ts
         │ ...etc
         └ package.json ← バックエンド用の packatge.json こっちにサーバーのビルド用scriptが書いてある

で、俺は開いた。VSCodeのタスクランナーを。意気揚々と。Command + shift + P からの task からの Enter ターンッ !! npm を選択して Enter ターンッ!!!

あれ?カレントディレクトリに package.json にない場合どうするんだ??? というか複数のpackage.jsonを扱いたい場合どうするんだ? 絶望しました。

まぁ、VSCodeには端末機能あるからそこでコマンド叩けばいいんだけど、やっぱりタスクランナーがあるんだったらそれでやりたい!!!

pacakge.jsonのscriptsの内容

client/package.json

フロント側のpackage.json webpack使ってビルドしてる。 webpackの方で、ビルドした.jsファイルを server/public/script/ に吐き出してる。 とりあえず VSCodeのタスクランナーから build と watch を叩きたい

{
  // 省略
  "scripts": {
    "build": "webpack --progress --colors --config webpack.config.dev.js",
    "watch": "webpack --progress --colors --watch --config webpack.config.dev.js",
    "build-product": "webpack --progress --colors --config webpack.config.prod.js",
    "watch-product": "webpack --progress --colors --watch --config webpack.config.prod.js"
  },
  // 省略
}

server/package.json

サーバー側のpackage.json 一番使ってるのが dev だから最悪これだけでもタスクランナーから叩きたい

{
  // 省略
  "scripts": {
    "start": "node ./app.js",
    "dev": "tsc --watch & node-dev ./app.js",
    "build": "tsc",
    "watch": "tsc --watch"
  },
  // 省略
}

結論

できた!

f:id:jBellTree:20170213143918p:plain

できた!

こうする!

これを(タスクの種類で npm を選んだ場合の初期状態)

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "npm",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [
        {
            "taskName": "install",
            "args": ["install"]
        },
        {
            "taskName": "update",
            "args": ["update"]
        },
        {
            "taskName": "test",
            "args": ["run", "test"]
        }
    ]
}

こうする!

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "0.1.0",
    "command": "sh",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "args": ["-c"],
    "tasks": [
        {
            "taskName": "build",
            "args": ["npm -prefix ./client run build && npm -prefix ./server run build;"]
        },
        {
            "taskName": "watch",
            "args": ["npm -prefix ./client run watch & npm -prefix ./server run dev;"]
        }
    ]
}

ポイント1

shコマンドを指定する。npmじゃなくてsh。発想の転換

    "command": "sh",

ポイント2

-cオプションをつける。 shellとか詳しくないけど、ようは端末で打った内容をそのまま実行するためのオプションらしい。

    "args": ["-c"]

ポイント3

args にもう全部書いちゃう!

    "args": ["npm -prefix ./client run build && npm -prefix ./server run build;"]

つまりこういうことだね。知らんけど。

$ sh -c npm -prefix ./client run build && npm -prefix ./server run build;

ポイント4

-prefix をつける。

npm -prefix ./client run build

https://docs.npmjs.com/cli/prefix

こういうことらしいです。

なるほどね ← 分かってない

ポイント5

&& とか & とか使って、フロント側の npm run と サーバー側の npm run をまとめて実行してやる。

今回は build の方は実行した一発だけでいいから &&(http://itpro.nikkeibp.co.jp/article/COLUMN/20060224/230604/) watchの方は両方はバックグラウンドで動かしたいから &(http://itpro.nikkeibp.co.jp/article/COLUMN/20060224/230589/) を使った。← よくわかってない。

npm -prefix ./client run build && npm -prefix ./server run build;
npm -prefix ./client run watch & npm -prefix ./server run dev;

まぁ、普段は IntelliJ使ってるんだけどな!!!!!!!!!!!