create-react-appで作ったプロジェクトをdevelopmentモードでbuildするには？

追記(2018/12/28)
この手の作業をやる場合はyarn ejectしてから行うべきだったようです

通常create-react-appで作ったプロジェクトをビルドすると圧縮されたソースが出力されてしまい出力ファイルと確認したい場合にはちょっと不便だったので

package.json内で呼ばれてるreact-scriptsの動作を追ってみて試行錯誤してみた話

ますは*/node_modules/react-scripts/の構成

```text
.bin → 今回は無視でOK
bin → react-scriptsコマンドを受け付けた際にまず実行されるスクリプト
config → 環境定義、パス、webpack.config.jsなどの定義
lib → 今回は無視でOK
LICENSE → 今回は無視でOK
node_modules → 今回は無視でOK
package.json → 今回は無視でOK
README.md → 今回は無視でOK
scripts → オプションで指定されたstartやbuildに対して実行する内容
template → 今回は無視でOK
template-typescript → 今回は無視でOK
```

####今回この環境をできるだけ非破壊でdevelopmentビルドを追加する手順で進める
create-react-appで制作したプロジェクト(※以後Reactプロジェクトとする)のpackage.jsonにdevコマンドを追加する
また*/はReactプロジェクトのルートディレクトリの意味で記載しているので各々の環境に置き換えて読んで下さい。

```diff:package.json
  "scripts": {
    "build": "react-scripts build",
+   "dev": "react-scripts dev",
  }
```
このコマンドを有効にするためにまず
*/node_modules/react-scripts/bin/react-scripts.js
にdevというオプションを許可するようにする

```diff:react-scripts.js
const scriptIndex = args.findIndex(
-  x => x === 'build' || x === 'eject' || x === 'start' || x === 'test'
+  x => x === 'build' || x === 'dev' || x === 'eject' || x === 'start' || x === 'test'
);
…略…
switch (script) {
  case 'build':
+ case 'dev':
  case 'eject':
  case 'start':
```
これでreact-scripts.jsはdevオプションを受け付けるようになったので実行スクリプトを用意する

とりあえず*/node_modules/react-scripts/scripts/内のbuild.jsをコピーして
同じ場所にdev.jsとして配置

試しにReactプロジェクトのトップにて

```terminal
$ yarn dev
($ npm run devでも可)
```

としてみると確かにyarn buildを実行した時と同様の出力結果が得られた

これでおよそ非破壊(経路追加のみ)なyarn devの実行経路が準備できたので実際にどうすればdevelopmentビルドができるのかの試行錯誤

まず先程コピーしたdev.jsの中身を見ると初っ端から

```js:dev.js
process.env.BABEL_ENV = 'production';
process.env.NODE_ENV = 'production';
```
というのがあるのでとりあえずこれを

```js:dev.js
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
```
と書き換えてからyarn devしてみると
*/node_modules/react-scripts/config/webpack.config.prod.jsにて以下の様な例外は発行された
throw new Error('Production builds must have NODE_ENV=production.');

どうやらここでprocess.env.NODE_ENVが'production'以外は認めないようになっていてthrowこのif文を黙らせた場合は結局productionビルドと同じ結果となった為意味はなさそう

そこでそもそもwebpack.config.prod.jsを参照している事自体がおかしいんじゃないかという事で参照を書き換えて

```diff:dev.js
-const config = require('../config/webpack.config.prod');
+const config = require('../config/webpack.config.dev');
```
再度yarn devしてみると以下のように該当のファイルがない旨のエラーに遭遇する
ENOENT: no such file or directory, open '*/build/static/js/main.chunk.js'

*/build/の中を見てみると確かにmain.chunk.jsというファイルはない
冷静になってReactプロジェクトのカレントディレクトリを見てみるとなんと
*/dist/というディレクトリが生成されておりその中に欲しかったdevelopmentビルドの結果が配置されている！

では上のエラーはなんだったのかというと…
*/dist/に出力後生成されたファイルのサイズを測ろうとして*/build/を探したらファイルがないというもの
webpackは基本的にはビルド結果を*/dist/に出力するようになっているので
webpack.config.prod.jsにそれを指定する記載があるはず…

ということでwebpack.config.prod.jsとwebpack.config.dev.jsを見比べたところ
以下のような出力先を以下のように指定されていた

```js:webpack.config.prod.js
module.exports = {
  output: {
    // The build folder.
    path: paths.appBuild,
  }
}
```

そこで非破壊のためwebpack.config.dev.jsをコピーしてwebpack.config.dev2.jsとして
scripts/dev.jsでも以下のようにdev2側を参照するようにした上で

```diff:dev.js
-const config = require('../config/webpack.config.dev');
+const config = require('../config/webpack.config.dev2');
```

webpack.config.dev2.jsに上記の設定を追加する

```diff:webpack.config.dev2.js
module.exports = {
  output: {
+   // The build folder.
+   path: paths.appBuild,
  }
}
```

これで再度yarn devを実行すると
正しくビルドが完了した。
試しにカレントディレクトリをbuildに移して

```terminal
$ cd build
$ http-server
（ない場合$ yarn global add http-serverなどで追加）
```
と実行してみると以下のように表示されたので正しそう
![react.png](https://qiita-image-store.s3.amazonaws.com/0/314532/034e7065-100e-cc05-5e10-b5e649937d5a.png)

ただし出力は完全一致はしていない
*/build/static/css
など幾つかのファイルがdevelopmentモードビルドではすくないのでもう少し調査が必要かも！？

###まとめ
・yarn dev (or npm run dev)を実行するための経路を準備
・webpack.config.dev.jsのコピーwebpack.config.dev2.jsにpath: paths.appBuildを追記してdev.js側で参照
・出力内容確認＆サーバー確認
・もしかしたら何か足りないかも？（要調査）
といったところ