Create React Appで出力されるラインセンスファイル関連の挙動変更

## 概要

- Create-React-Appで作成し、buildしたファイルのライセンスコメント関連の出力をいじりたい

という内容です。

## やりたかったこと

- フロントエンドで使用しているライブラリの条文を`yarn licenses generate-disclaimer`で自前出力して、公開したい
- ライセンス条文ファイルが無かったりして`yarn licenses generate-disclaimer`で拾えないものは手動で追記したい
- buildされたjsファイルのコメントを自前ファイルに関する内容に変更したい
といった感じです。

結論を先に言うと、

- `yarn build`時に`static/js`以下に固定名のLICENSEファイルを自前で配置する
    - `build`タスクを、`yarn build`が走る前に以下をするように変更
        - `yarn licenses generate-disclaimer`の結果をpublic/static/js以下に出力する
        - 追記したいファイルの内容をライセンスファイルに追記する
- react-app-rewiredを利用して、minimizeしたファイルの先頭に自前配置したライセンスファイルへの言及させる

といった感じで対応しました。
自前でライセンスファイルを作成する部分は`/public`以下にファイルを置けばいいだけなのですが、
↓のようなビルドさせたファイルの先頭コメントを、ejectせずにどうやって変えるかの話になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/a0097eed-bdfb-cc0d-3aaf-6a5445d956bb.png)


## ライセンス関連出力の振る舞いを変える

### デフォルトで出力されるライセンスファイル

`create-react-app`したものを`yarn build`すると`build/statis/js`以下にこんな感じで出力されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/6ee9c137-e0d7-3620-3695-e229965b64f9.png)

`main.xxxxx.LICENSE.txt`の中身はこんな感じです

```
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

/** @license React v0.20.2
 * scheduler.production.min.js
 *
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

...
```

加えて、`main.xxxxxx.js`の先頭にこんな感じのコメントが入ります。

```
/*! For license information please see main.93b92443.js.LICENSE.txt */
```


`@license/@preserve/@cc_on`でソース内にコメントを入れると、上記ファイルに追記されます。
App.txtに適当にコメントを入れてみます。

```
// App.txt

/**
 * @license これはライセンスコメントです。
 */

/**
 * @preserve これも追記されます。
 */

/**
 * @cc_on これも残されます。
 */
 
/**
 * @comment これは残りません。
 */
function App() {
...
```

とソース内にコメントすると、ライセンスファイルには

```
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

/**
 * @cc_on これも残されます。
 */

/**
 * @license これはライセンスコメントです。
 */

/**
 * @preserve これも追記されます。
 */

/** @license React v0.20.2
 * scheduler.production.min.js
 *
...
```

と出力されます。`/^\**!|@preserve|@license|@cc_on/i`で拾っているみたいです。

### この振る舞いを変更するには？

webpackのconfig設定をすればいいのですが、ejectしたくない場合は[react-app-rewired](https://github.com/timarney/react-app-rewired)や[craco](https://github.com/gsoft-inc/craco)といったライブラリを使用して、ejectせずに設定をいじれるようにします。 　
ここでは`react-app-rewired`を使って試してみます。

#### react-app-rewiredをインストール
```
yarn add -D react-app-rewired
```

#### react-scriptsをreact-app-rewiredに変更

```diff
   "scripts": {
     "start": "react-scripts start",
-    "build": "react-scripts build",
+    "build": "react-app-rewired build",
     "test": "react-scripts test",
     "eject": "react-scripts eject"
   },
```

#### config-override.jsをプロジェクトのトップに作成

`@comment`も拾うようにしてみます。
`TerserPlugin`を使っていますが、Create-React-Appで入っているのでそのまま使えます。

```javascript
// config-override.js

const TerserPlugin = require("terser-webpack-plugin");

module.exports = function override(config) {
  return {
    ...config,
    optimization: {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          extractComments: /^\**!|@preserve|@license|@cc_on|@comment/i,
        }),
      ],
    },
  };
};
```

#### ビルドする

`yarn build`してみます。

```
// LICENSE.txt

/*
object-assign
(c) Sindre Sorhus
@license MIT
*/

/**
 * @cc_on これも残されます。
 */

/**
 * @comment これは残りません。
 */

/**
 * @license これはライセンスコメントです。
 */

/**
 * @preserve これも追記されます。
 */

/** @license React v0.20.2
```

`@comment`も拾うようになりました。

あとは[Terser Plugin](https://github.com/webpack-contrib/terser-webpack-plugin)のドキュメントを見て、好きにいじります。

↓な感じで変えてやれば

```javascript
// config-override.js

const TerserPlugin = require("terser-webpack-plugin");

module.exports = function override(config) {
  return {
    ...config,
    optimization: {
      minimize: true,
      minimizer: [
        new TerserPlugin({
          extractComments: {
            banner: () => {
              return `ライセンスはここを見て！ -> LICENSE.txt`;
            },
          },
        }),
      ],
    },
  };
};
```

こんな感じでコメントを変えられるので(開発者ツールのsourceです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408437/40785232-7690-c694-f872-529f42a1635e.png)

自前で用意したラインセスファイルに関するコメントを好きに設定できます。