ReactのTypeScript開発環境、俺ならこうやる 2017年2月5日版

ちきさんです。

[Angular2の開発環境、俺ならこうやる 2016年7月25日版(2.0)](http://qiita.com/ovrmrw/items/56364a4b673c03e20bba) というエントリーを過去に書きまして、最近よくReactを使うようになったのでReact版を書こうかと思った次第です。

GitHubリポジトリはこちら→ [ovrmrw/create-react-app-typescript-starter](https://github.com/ovrmrw/create-react-app-typescript-starter)

大前提としてスクラッチで環境を作ることはしません。create-react-appをテンプレートにします。一部の内容は [create-react-appでTypeScript用のReact開発環境を作る(入門者向け)](http://qiita.com/ovrmrw/items/5e573cff401929a3ed72) と被りますがご容赦ください。

では始めましょう。
npmの代わりにyarnを使ってもOKですし僕はyarnを使いますが説明はnpmで統一します。

## create-react-appをインストール

```
$ npm i -g create-react-app typescript tslint
```

## 新しいプロジェクトを作る

```
$ create-react-app my-app
$ cd my-app
```

## TypeScriptで使いたいので環境を一旦破壊する

```
$ npm run eject
```

## TypeScript環境をインストールする

TypeScriptでReact開発するのに最低限必要なものをインストールします。

```
$ npm i -D typescript tslint light-ts-loader @types/react @types/react-dom @types/node
$ npm i -S tslib
```

## Routing環境をインストールする

いくつか試してみた結果react-routerが定番っぽいし良さそうでした。ただ、よりAngularに近そうなのは `ui-router-react` かなと思ったのでこれも入れておきましょう。

```
$ npm i -D @types/react-router
$ npm i -S react-router ui-router-react
```

## テスト環境をインストールする

TypeScriptでテストを書けるようにします。定番のenzymeも導入します。

```
$ npm i -D jest ts-jest enzyme react-addons-test-utils @types/jest @types/enzyme
```

## RxJSをインストールする

どう考えてもこれは必要です。

```
$ npm i -S rxjs
```

## DI(Dependency Injection)環境をインストールする

Angular出身者はDIがないと落ち着かないですね。

```
$ npm i -S inversify inversify-inject-decorators reflect-metadata
```

## ovrmrw-reactive-storeをインストールする

Fluxの簡易版です。状態管理するのに便利らしいですよ。

```
$ npm i -S ovrmrw-reactive-store
```

## Jestのconfigを別ファイルに書き出す

デフォルトでは `package.json` にJestのconfigが書かれていて管理しにくいです。なので下記のように別ファイルに書き出しつつ、 `package.json` の `scripts` では `--config=jest.config.json` というオプションを付けます。

JestのconfigはデフォルトではJSを前提としているため、TypeScriptに対応させるには色々書き換える必要があって把握するのに少々時間がかかりますが、とりあえず下記のように書いておくと概ね動作するでしょう。

```json:jest.config.json
{
  "collectCoverageFrom": [
    "src/**/*.{js,jsx,ts,tsx}"
  ],
  "setupFiles": [
    "<rootDir>/config/polyfills.js",
    "<rootDir>/testing/polyfill.js"
  ],
  "transform": {
    "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest",
    "^.+\\.css$": "<rootDir>/config/jest/cssTransform.js",
    "^(?!.*\\.(js|jsx|css|json|ts|tsx)$)": "<rootDir>/config/jest/fileTransform.js",
    "^.+\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest/preprocessor.js"
  },
  "testPathDirs": [
    "<rootDir>/src"
  ],
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(js|jsx|ts|tsx)$",
  "testResultsProcessor": "<rootDir>/node_modules/ts-jest/coverageprocessor.js",
  "moduleFileExtensions": [
    "js",
    "jsx",
    "json",
    "node",
    "ts",
    "tsx"
  ],
  "moduleNameMapper": {
    "^react-native$": "react-native-web"
  },
  "verbose": true
}
```

```json:package.json
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --config=jest.config.json",
  },
```

## テスト用のpolyfillを用意する

僕の場合下記のライブラリは必須なのでこういうpolyfillを先に作っておきます。

- `reflect-metadata` ... DIするのに必要
- `rxjs` ... フロントエンド書くのに必要

```js:testing/polyfill.js
require('reflect-metadata')
require('rxjs/Rx')
```

## configフォルダのいくつかのファイルを変更する

configフォルダは自動生成されるフォルダなのでこの中は極力いじりたくないです。ですがいくつかのファイルは変更を余儀なくされるのでそこはやむを得ないでしょう。

- [config/paths.js](https://github.com/ovrmrw/create-react-app-typescript-starter/blob/master/config/paths.js)
- [config/webpack.config.dev.js](https://github.com/ovrmrw/create-react-app-typescript-starter/blob/master/config/webpack.config.dev.js)
- [config/webpack.config.prod.js](https://github.com/ovrmrw/create-react-app-typescript-starter/blob/master/config/webpack.config.prod.js)

上記のファイルを一部変更しています。変更箇所には `// @ovrmrw` というコメントを残してあるので探してみてください。

## tsling.jsonを生成する

```
$ tslint --init
```

このコマンドでルートに `tslint.json` が生成されます。後は自分の好きなように変更してください。

- [tslint.json](https://github.com/ovrmrw/create-react-app-typescript-starter/blob/master/tslint.json)

## tsconfig.jsonを生成する

```
$ tsc --init
```

このコマンドでルートに `tsconfig.json` が生成されます。
これを僕なら下記のように変更します。

```json:tsconfig.json
{
  "compilerOptions": {
    "outDir": ".dest-tsc",
    "module": "commonjs",
    "moduleResolution": "node",
    "target": "es5",
    "jsx": "react",
    "lib": [
      "es2017",
      "dom"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "importHelpers": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "include": [
    "src/**/*"
  ]
}
```

`src` フォルダにも `tsconfig.json` を作ります。

```json:src/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "sourceMap": true,
    "strictNullChecks": true,
    "skipLibCheck": true
  }
}
```

使い分けの理由は [ここ](http://qiita.com/ovrmrw/items/5e573cff401929a3ed72#tsconfigjson%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B) で述べています。

## 最後に

環境作りはここまでです。
GitHubリポジトリもあるので [ovrmrw/create-react-app-typescript-starter](https://github.com/ovrmrw/create-react-app-typescript-starter) をcloneしたら手っ取り早いですね。

あとはsrcフォルダに好きにコードを書くだけです。