create-react-appを使わずにReactの環境構築をして周辺ツールとかを理解する

Reactに入門したのはいいもののcreate-react-appでプロジェクトを作成すると無駄なファイルが多かったり、環境構築を丸投げしてるのでちょっと色々まずいなと思い、
create-react-appを使わずに環境構築をしていこうと思います。[ドキュメント](https://github.com/facebook/create-react-app#popular-alternatives)を見ると学習用やちょっと試したいときに最適である的なことが書いてありますね。



---

以下はこの記事での手順をまとめたスクリプトです。npmが入っている前提ですが、実行ディレクトリにプロジェクトが生成されると思います。

<details><summary> 最終的なスクリプト </summary><div>

```sh
PROJECT_NAME=myapp
echo $PROJECT_NAME
mkdir $PROJECT_NAME
cd $PROJECT_NAME

cat <<EOF > package.json
{
 "scripts": {
    "dev": "webpack-dev-server --open"
  }
}
EOF

npm i react react-dom webpack webpack-cli
npm i -D typescript ts-loader webpack-dev-server @types/{react,react-dom}


mkdir dist
mkdir src

cat <<EOF > dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title> my-app </title>
</head>
<body>
  <div id="root"></div>
  <script src="bundle.js"></script>
</body>
</html>
EOF

cat <<EOF > src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';

const App = () => <div> hello word </div>

ReactDOM.render(<App/>, document.getElementById("root"))
EOF

cat <<EOF > tsconfig.json
{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "allowSyntheticDefaultImports" :true
  }
}
EOF

cat <<EOF > webpack.config.js
const path = require('path');

module.exports = {
  mode: "development",
  entry: './src/index.tsx',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js' ],
  },
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist',
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  }
};
EOF
```

</div>
</details>

実行後は以下のようになると思います。

```
├── dist
│   └── index.html
├── package-lock.json
├── package.json
├── src
│   └── index.tsx
├── tsconfig.json
└── webpack.config.js
```



## 必要なモジュール

- React/ReactDOM
- webpack
 - ソースコードを1つのファイルにまとめるツール。v4 から cli も必須になった。
- webpack-dev-server 
 - Hotリロード機能。
- トランスパイラ
 - babel, ts-loaderとか
 - classとかJSXとかトランスパイルしてJavaScriptコードを生成する。
 
 
 npmでいれる。
 
 ```
 npm i react react-dom webpack webpack-cli
 ```
 
 typescriptを使う場合は型定義とかも
 
 ```
 npm i -D typescript ts-loader webpack-dev-server @types/{react,react-dom}
 ```

## 作成するファイル

- index.html
- index.js
- package.json
- ts-config.json
- webpack.config.js

### index.html

`index.html`

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>my-app</title>
  </head>
  <body>
    <div id="root"></div>
    <script src="bundle.js"></script>
  </body>
</html>
```

htmlファイル。webpackでbundleしたファイルを読み込む。

### index.ts

`src/index.tsx`

```typescript
import React from "react"
import ReactDOM from "react-dom"

const App = () => <div> hello word </div>

ReactDOM.render(<App />, document.getElementById("root"))
```

エントリーファイル。Hello Worldだけ。

### tsconfig.json

`tsconfig.json`

```json
{
  "compilerOptions": {
    "outDir": "./dist/",
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "allowJs": true,
    "allowSyntheticDefaultImports": true
  }
}
```

とりあえず公式のと同じです。適宜追加していきます。

### webpack.config.js

webpackの設定ファイルです。初見ででかいconfigファイルを見るとビビってしまいますが、最低限必要なのはそこまで多くないです。

https://webpack.js.org/guides/typescript/
https://webpack.js.org/concepts/

`webpack.config.js`

```js
const path = require("path")
module.exports = {
  mode: "development",
  entry: "./src/index.tsx",
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: "ts-loader",
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
  devtool: "inline-source-map",
  devServer: {
    contentBase: "./dist",
  },
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
}
```

mode(dev or prod)と入出力パスとloaderとresolveなんで簡単ですね。


この部分はwebpack-dev-serverの設定です。

```
  devtool: "inline-source-map",
  devServer: {
    contentBase: "./dist",
  },
```

https://webpack.js.org/guides/development/#using-webpack-dev-server

### package.json

`npm init -y`みたいにすると雛形が生成されますが、最低限ファイルがあればいいようです。

``` json
echo "{}" > package.json
```

```
npm i react, react-dom
```

あとオプションが微妙ですね。

`--save-dev | -D`でdevDependencyに追加
`--save | -S`で両方とかですかね？？


npxはローカルにインストールしたパッケージを実行できる（正確ではないかも）

```
npx webpack-dev-server --open
```

`npm script`に追記して

``` json
{
  "scripts": {
    "start": "webpack-dev-server --open"
  }
}
```

```
npm run start
```

で実行できるようになる。

--- 

あとは適当にテストとかlinterとかいれるだけ。


...用語とか言葉とかあやふやなところ適宜修正します。


## その他

#### git

```
echo "node_modules" > .gitignore
git init
git add .
git commit -m "create project"
```

#### styled-components

```
npm i styled-components
npm i @types/styled-components
```