Reactのcreate-react-appで作成したサイトのimportを絶対パスにするしVScodeでパス補完もするし

相対パスでimportしていると「俺はあといくつ`.`キーを叩けばいいのか。いっそ階層という概念を捨ててすべてのファイルを同じ場所に置けば管理もしやすいのではないか。しかし見づらいからやめておこう。俺はあといくつ`.`キーを叩けばいいのか」という哲学に必ずぶつかると思います。

それならrootを設定して絶対パスでimportすればいいのさ！
と、vueやangularは教えてくれます。

さっそくtsconfigにroot設定を書いて`yarn start`したら反映されないどころか、その記述が消えるという謎の挙動で憤怒。

どうやらcreate-react-appで作成した場合、tsconfig.json内の`"compilerOptions": {}`
がビルド時にクリーンされる。これは20190307現在、正しい挙動だそうです。マジ憤怒。

それでは解決していきましょう。

### 解決させること
- reactのcreate-react-appでサイトを作成したときのimportを相対パスから、'@'で始まる、絶対パスにしたい
- ビルド時にクリーンされるtsconfig.jsonのcompilerOptions内は触らない。
- VScodeでのファイルジャンプとパス補完は効いたままにする

#### notice
- react + typescript + vscode環境向け
- webpackのconfigでresolveさせない。babelrcもさわらない。最高！！
- ejectはしない。したくない。
- linterも"tslint-react"であれば怒られません。
- **しかしながら、ハックな解決策です。**
- facebook/create-react-appが、いずれ公式で対応すると言っていますのでそれまでの暫定と考えておきましょう。
  - https://github.com/facebook/create-react-app/issues/5118 で議論されています。
  - この議論の中で[解決策を提示してくれていた人](https://github.com/facebook/create-react-app/issues/5118#issuecomment-464025389)がいたので、それにvscodeの設定を追加したエントリーです。

---
## 手順 & 目次
1. [react-app-rewiredというconfig上書きパッケージを追加](#1-react-app-rewiredというconfig上書きパッケージを追加)
2. [package.jsonのscripts内の`react-scripts`を`react-app-rewired`に書換える](#2-packagejsonのscripts内のreact-scriptsをreact-app-rewiredに書換える)
3. [configを上書きするjsを設置](#3-configを上書きするjsを設置)
4. [tsconfigとは別にtsconfig.paths.jsonを作成](#4-tsconfigとは別にtsconfigpathsjsonを作成)
5. [tsconfig.jsonに"extends": "./tsconfig.paths.json"を追記](#5-tsconfigjsonにextends-tsconfigpathsjsonを追記)
6. [vscodeのsettings.jsonに追記](#6-vscodeのsettingsjsonに追記)
7. [vscode再起動](#7-vscode再起動)

手順5までで絶対パスimportが可能になります。

手順6はvs codeのファイルジャンプとパス補完機能を有効化するものです。

---
## 1. react-app-rewiredというconfig上書きパッケージを追加
[react-app-rewired](https://github.com/timarney/react-app-rewired)をパッケージに追加しましょう

```
yarn add -D react-app-rewired
```

create-react-appのversionによってaddするパッケージが異なります。
公式reademeをみてaddしましょう。
<https://github.com/timarney/react-app-rewired#how-to-rewire-your-create-react-app-project>


## 2. package.jsonのscripts内の`react-scripts`を`react-app-rewired`に書換える
暫定対応にもかかわらずpackage.jsonをいじるので、script新たに追加したほうがいいかもしれません。

ここではとりあえず、既存のstartを書き換えます。

```json5:package.json
  "scripts": {
    "start": "react-scripts start" //最初はこうなっています
  }
  ↓
  "scripts": {
    "start": "react-app-rewired start" //こう書き換えます。start以外も同様に。
  }
```

## 3. configを上書きするjsを設置
rootディレクトリに`config-overrides.js`を追加。
中身はこう↓

```js:config-overrides.js
const path = require('path');

module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: { '@': path.resolve(__dirname, 'src') },
  };

  return config;
};
```

## 4. tsconfigとは別にtsconfig.paths.jsonを作成
tsconfig.paths.jsonをrootに作成。中身はこちら↓

```json5:tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
    "@/*" : ["src/*"]
    },
  }
}
```

## 5. tsconfig.jsonに"extends": "./tsconfig.paths.json"を追記
tsconfig.jsonに追記しましょう。(typescriptじゃない場合はjsconfig.json)

```json5:tsconfig.json
{
  ...,
  "extends": "./tsconfig.paths.json" //最後の行とかにいれときます。
}
  
```
ここまででimportを絶対パスに書き換えることができるようになりました。



↓相対パスと絶対パスimportの違いです。

```typescript
//相対パス
import Modal from '../../../components/modal'

//絶対パス
import Modal from '@/components/modal' 
```
見やすい！！！

## 6. vscodeのsettings.jsonに追記
絶対パスにできたけれど、手順5までだとvscodeでファイルジャンプとパス補完が効きません。

vscodeのsettings.jsonをいじると他のプロジェクトに移動したときにその設定に引きづられます。
それは困るのでプロジェクトルートに`.vscode`ディレクトリを作りそのなかに`settings.json`を作成します。

```
$ mkdir .vscode
$ touch .vscode/settings.json
```

settings.jsonの中身はこう↓

```json5:settings.json
{
  "path-autocomplete.pathMappings": {
    "@": "${folder}/src"
  }
}
```
path-autocompleteはvscodeインストールすると最初から使用できますが、
拡張としても配布されていますので、もしvscodeにpath-autocompleteがなければ拡張をインストールしておきましょう。

## 7. vscode再起動
マジ大事。

これでファイルジャンプもパス補完もできるようになっているかと思います。

できているgifです。
![import-path.gif](https://qiita-image-store.s3.amazonaws.com/0/51031/eea85f23-767e-b852-6238-5858ce17f17a.gif)
やったね！！！


## 参考
https://qiita.com/ymkz/items/8f09326382ed7ebcd061
https://github.com/facebook/create-react-app/issues/5118#issuecomment-464025389