React-TypescriptでSPAアプリを作る


#動機
jQuery、AngularとJavascriptフレームワークを経験してきたが、
最先端のJavascript界隈から取り残されているのではないかという危機感から
Reactに手を出す事を決めました。
また、サーバーサイドがTypescriptなので、フロントもTypescriptに合わせる事で言語を統一させるという目的もあります。

#アプローチ
今まではAngular1系、Babel、Gulp、Bower、SASSでSPAアプリ作っていました。
それぞれについてReact移行する際に必要かどうかネット検索しました。

ポイントはシンプルに構成をまとめるという点です。利便性よりもその点を重視していきたいと思います。

#### Angular
→Reactに置き換え（決定済み）、状態管理にReduxも使う
#### Babel
→react-scripts-tsで必要なので、継続使用。多くのブラウザをサポートするにはes5にトランスパイル必要
#### Gulp
→Webpackに置き換え
#### Bower
→Yarnに置き換え（Bowerが非推奨のため）
#### SASS
→継続使用

#Yarnを使ってReact環境構築
node.js（安定版）とnpmをインストールします。
※windowsは公式node.jsサイトの推奨版をDL,Installして下さい。Chocolateyなどのパッケージ管理からのインストールでも可です。

```
brew install nodebrew
nodebrew setup
export PATH=/usr/local/var/nodebrew/current/bin:$PATH
export PATH=$HOME/.nodebrew/current/bin:$PATH
source .bash_profile
nodebrew install-binary v8.11.2
nodebrew use v8.11.2
```

npmよりもyarnが早くて使いやすいので、yarnをインストール
※windowsは公式yarnサイトの安定版をDL,Installして下さい。Chocolateyなどのパッケージ管理からのインストールでも可です。

```
brew install yarn
```

yarn addはnpm install --saveと同意でインストール(node_modulesへのパッケージ配置)とpackage.jsonの追記を行います。
yarnを実施すると、yarn.lockファイルが作成されます。
package-lock.jsonと同じ役割で、依存するモジュールのバージョンを固定することができます。

※パッケージをインストールし直したい場合はyarn.lockを削除してからyarn(yarn install)を実行します。

react-typescript環境を構築します。
※便利なのでcreate-react-appをインストールします。

```
npm install -g create-react-app

create-react-app アプリ名 --scripts-version=react-scripts-ts
```

create-react-appコマンドを叩くと、アプリ名のディレクトリ配下にファイルを作成してくれます。便利です。

```
アプリ名
├── .gitignore
├── README.md
├── images.d.ts
├── package.json(react、react-domなど追加)
├── node_modules
├── public
│   ├── favicon.ico
│   └── index.html
└── src
    ├── App.css
    ├── App.tsx
    ├── App.test.tsx
    ├── index.css
    ├── index.tsx
    ├── registerServiceWorker.ts
    └── logo.svg
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.test.json
└── tslint.json
```

reactアプリ起動

```
cd アプリ名
yarn start
```

これだけReact-Typescriptアプリの起動は出来ます。原子が回転してる例のスタートページです。

#Webpack、SASS環境構築
webpackをインストールします。

```
yarn add webpack webpack-cli
```

package.jsonのscriptsにbuildを修正して、devel追加しました。
yarn run devel、yarn run buildでwebpackをdev、prodモードで分けて起動できるようにしました。

```package.json
  "scripts": {
    "start": "react-scripts-ts start",
    "devel": "webpack --mode development",
    "build": "webpack --mode production",
    "eject": "react-scripts-ts eject",
  }
```

webpack.config.js設定
ローダーの設定が必要なので追記していきます。sassを読み込めるように
設定を追加していきます。

```webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const MODE = 'development';
const devMode = process.env.NODE_ENV !== 'production';

module.exports = {
  devtool: "source-map",
  mode: MODE,
  entry: {
    'index': [
      path.resolve(__dirname, 'src/index.tsx')
    ],
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'public'),
    publicPath: '/',
  },
  resolve: {
    extensions: ['.ts','.tsx', '.js', '.jsx', '.css', '.scss'],
  },
  module: {
    rules: [
      {
          test: /\.(js|jsx)$/,
          use: {
              loader: 'babel-loader'
          }
      },
      {
          test: /\.(ts|tsx)$/,
          use: {
              loader: 'ts-loader'
          }
      },
      {
          test: /\.css$/,
          use: [
              'style-loader',
              'css-loader'
          ]
      },
      {
          test: /\.scss$/,
          use: [
              MiniCssExtractPlugin.loader,
              {
                  loader: 'css-loader',
                  options: {
                      url: false,
                      minimize: true,
                      sourceMap: true
                  }
              },
              'sass-loader'
          ],
      },
      {
          test: /\.(png|jpg|jpeg|gif|svg|ico)$/,
          use: [
              {
                  loader: 'url-loader',
                  options: {
                      limit: 8192
                  }
              }
          ]
      }
    ]
  },
  performance: { hints: false },
  plugins: [
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
    }),
    new MiniCssExtractPlugin({
      filename: devMode ? '[name].css' : '[name].[hash].css',
      chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
    })
  ]
};
```

js、ts、cssなどのファイルを読み込むためには、
webpackのローダーを設定する必要があります。

イマココです。
社内のための手順紹介なので、追記していきます。