Umi Uyuraのブログ

プログラミング関連の作業ログ

NW.jsのパッケージング方式の見直し

先日、自分用のReactのプロジェクトテンプレートの構造を見なおしたついでに、 React + NW.jsのテンプレートの方 (umi-uyura/react-on-nwjs-sample) も同じ方針で改良しておくことに。

umi-uyura.hatenablog.com

ついでに、以前のテンプレートでは配布形式の作成時に問題があったので、その点を改善しておくことにしました。

devDependenciesも含んでしまっていた問題

以前は node-webkit-builder(現nw-builder)を使って、以下のようなコマンドを実行するようにしていました。

$ nwbuild -p osx64,win64 .

これを実行すると、プロジェクト直下のソースや node_modules などを一括で含めて、プロジェクト直下の build というフォルダ内にパッケージングされたアプリが生成されます。

ところが、当たり前なのですが、そのままだと開発時にしか使わない devDependenciesnode_modules も含んでパッケージ化されてしまいます。その中には、 node-webkit-builder自身なども含まれるため、ただでさえサイズが大きくなるNW.jsアプリのサイズが、さらに膨れ上がってしまっていました。

devDependenciesを含まないようにする

npm コマンドで、 devDependencies を含まないようにするには、 npm install --production を実行すれば良いのですが、開発環境には必要なので、プロジェクト直下で実行するわけにはいきません。

そこで、配布形式を作成する用のテンポラリのフォルダ build を作成し、そこにコピーしたpackage.jsonを使って、 $ npm install --production を実行すれば良いと思いつきました。

流れとしては、いったん必要なファイルを build フォルダへコピーした後、

# buildフォルダ内で配布用の依存関係のみインストール
$ cd build && npm install --production

# buildフォルダの中身をベースにパッケージングして、distフォルダへ出力
$ nwbuild -p osx64,win64 -o dist build

という感じで実行することで、 devDependencies のモジュール類を含めずに、必要なものだけでパッケージングできるようになりました。

配布時にはpackage.jsonを変更したい問題

  • toolbarは、開発中は表示しておきたいが、配布時には消したい
  • エントリポイントは、開発中は app/index.html だが、配布時には index.html にしたい

NW.jsベースでアプリを作ってみると、開発中と配布時でpackage.jsonの内容を少し変えたい場面がありました。

具体的には、

  • window.toolbar は、開発中はChromeデベロッパツールを呼び出したりしたいために表示しておきたいが、配布時には消したい
  • エントリポイント( main )は、開発中は app/index.html にしているが、配布時には app フォルダの中身を app.nw の直下に置きたいので、 index.html にしたい

といったものです。

jsonコマンドを使った開発用package.jsonの用意

単純な解決方法は、リリース用のpackage.jsonを用意してしまうことですが、基本的な内容は変わらないため、二重管理となってしまいます。

そこで、 json コマンド( trentm/json )を使って、配布用を作成する際のテンポラリフォルダへpackage.jsonをコピーする際、配布用の設定とマージすることで、実現することにしました。

コマンドでマージする2つのファイルを cat で合成して標準出力へ流し、それをパイプで json コマンドへ渡します。

同じキーに対応する値が複数ある場合は、後から入力したものが優先されるので、配布用の設定を後にしています。

$ cat package.json package-dist.json | json --merge > build/package.json

プロジェクト構造の見直し

基本的な方針は、先日の umi-uyura/my-react-boilerplate と同じようなフォルダ構造にしつつ、上記の配布形式の見直しに伴って build フォルダと配布用のpackage.jsonの差分 package-dist.json を加えた、以下のような形になりました。

.
├── README.md
├── app
│   ├── css
│   ├── index.html
│   └── js
├── build
├── dist
├── node_modules
├── package-dist.json
├── package.json
└── src
    └── jsx

Material UIも加えた方のテンプレートも、同じ方針で修正しておいた。

umi-uyura/react-nwjs-materialui-sample

参考