[Webpack/React/Typescript]2024年にreactアプリを立ち上げる手順

# はじめに
こんにちは。今日もフロントに関する投稿です（最近はバックエンドばかりやっていたけど）。
Reactの新規プロジェクトを立ち上げる際に、皆さんは何を使いますか？
私はなぜかwebpackが好きですが、初期設定や配置が大変です。自分もよくところどころに詰まっていました。こんなwebpackですので、今回は私から自分の立ち上げる手順を記載してみます。
環境については、node 20.15.0を使い、そしてwebpackなどのバージョンは特に指定せず、nodeが決めてもらいます。

# ファイル構成
```
project
├ src
│ ├ app
│ │ └ app.tsx
│ └ index.tsx
├ .babel.config.js
├ index.html
├ package.json
├ tsconfig.json
└ webpack.config.js
```

# 設定手順
## 1. インストール
まずはwebpack関連の物を入れます。
```shell
npm i --save-dev webpack webpack-cli webpack-dev-server
```
※ここで、webpackの初期化ができます。下記を実行したら、webpackからあらゆるファイルを作成します。もちろん必須ではないです。
```shell
npx webpack init
```
loaderを入れます（webpack初期化された場合、これらはすでにインストール済かも）。
```shell
npm i --save-dev babel-loader css-loader ts-loader style-loader
```
babelに必要なライブラリーを入れます。
```shell
npm i --save-dev @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript
```
reactを入れます。
```shell
npm i react react-dom react-router-dom
```
これで基本動作用のライブラリーがそろっています（はず）。

## 2. package.jsonの設定
上記インストールが終わったら、package.jsonの中に`dependencies`と`devDependencies`の下にライブラリーがいっぱい入っています。これからpackage.jsonの残る部分を設定していきます。
まずは`scripts`を設定します。ここはwebpack初期化された場合、すでにいくつかコマンドがあるはずです。
```json
"scripts": {
    "build": "webpack --mode=production --node-env=production",
    "watch": "webpack --watch",
    "build:dev": "webpack --mode=development",
    "build:prod": "webpack --mode=production --node-env=production",
    "start": "webpack-dev-server"
}
```

## 3. .babel.config.jsの設定
babelはreactとtypescript用の.tsxファイルなどをコンパイルするので、事前設定が必要です。中身は以下です。
```js
module.exports = {
  presets: [
    "@babel/preset-env",
    "@babel/preset-react",
    "@babel/preset-typescript",
  ]
}
```

## 4. webpack.config.jsの設定
Webpackの配置は大事です。ややこしいけど、うまく設定しなかったら実行した際に失敗したりエラー出たりします。

### modeの出し分け
開発用・リリース用それぞれ設定が異なるので、まずはmodeの出し分けを設定します。
```js
module.exports = () => {
    if (isProduction) {
        config.mode = 'production';
        
        config.plugins.push(new MiniCssExtractPlugin());
        
        
    } else {
        config.mode = 'development';
    }
    return config;
};
```
`config`は`mode`以外の配置を入れます。これから設定していきます。
もちろん、開発用・リリース用それぞれ別`config`を利用するには可能です。

### entry
Webアプリのバンドリングする際最初に行くところです。ここでHTMLのルートを指定してアプリをレンダリングするファイルを入れます。
```js
entry: './src/index.tsx',
```

### output
Webpackでプロジェクトをビルドした際に、成果物に関する設定です。ここでgit管理外の`dist`フォルダを指定します。
```js
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js',
},
```

### devServer
ローカルでテストサーバを立ち上げる際に、関連の設定です。
```js
devServer: {
    open: true, // ビルドが完了したら自動的に開くフラグ
    host: 'localhost',
    static: { // 追加静的ファイルの場所。ここは同じくdistを指定
        directory: path.join(__dirname, 'dist')
    },
    port: 8080,
},
```

### module
Webpack実行時に必須なモジュールの配置をここにいれます。
```js
module: {
    rules: [
        { // 最初はbabelの配置になる。順番変更不可
            test: /\.tsx$/i,
            loader: 'babel-loader',
            options: { presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-typescript']},
        },
        {
            test: /\.(ts|tsx)$/i, // .tsxはbabelが扱うので、ここはtsだけでも良い…かな
            loader: 'ts-loader',
            options: {
                configFile: path.resolve(__dirname, 'tsconfig.json')
            },
            exclude: ['/node_modules/'],
        },
        { // ここからは自由設定
            test: /\.css$/i,
            use: [stylesHandler,'css-loader'],
        },
        {
            test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i,
            type: 'asset',
        },
    ],
},
```

### plugins
HTMLテンプレートを使うので、プラグインは必須です。これがないと正確に立ち上げるのはできません。
```js
plugins: [
    new HtmlWebpackPlugin({
        template: './index.html',
    }),
],
```

### その他
```js
resolve: {
    extensions: ['.tsx', '.ts', '.jsx', '.js', '...'],
},
target: "web"
```

## 5. tsconfig.jsonの設定
Typescriptを使うには、tsの設定が必須です。
もちろん、javascriptを使う場合、これは不要です。
```json
{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "noImplicitAny": true,
    "module": "es6",
    "target": "es5",
    "jsx": "react",
    "moduleResolution": "Node",
    "allowJs": true
  },
  "include": ["./src"],
  "exclude": ["./node_modules"]
}
```

## 6. index.htmlの実装
ここまで設定が完了したので、次は実際にレンダリングされる物を書きます。
index.htmlとはテンプレートで、webアプリのベースファイルのようなものです。ここで基本動作に向けて例を出します。セキュリティ（CSPなど）関連の設定が入っていないです。
```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="stylesheet" href="https://rsms.me/inter/inter.css" />

    <title>My React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script type="module" src="/main.js"></script>
  </body>
</html>
```
index.htmlにはIDが`root`である要素は必要です。Reactアプリはこの要素にレンダリングします。

## 7. index.tsxの実装
Webアプリのバンドリングはindex.tsxから始まります。index.tsxには下記の実装が必須です。
- レンダリング先の指定（index.htmlの`root`要素）
- アプリの指定

```js
import * as React from 'react';
import { createRoot } from 'react-dom/client';

import App from './app/app';

const root = document.getElementById('root');
if (!root) throw new Error('No root element found');

createRoot(root).render(
  <App />
);
```

## 8. app.tsxの実装
アプリの実装は皆さんが詳しい領域でしょう。ここは例だけ出します。
```tsx
import * as React from 'react';

function App () {
  return (
    <div>Hello react!😀</div>
  )
}

export default App;
```

# まとめ
上記実装が終わったら、`npm start`でアプリを起動できます。
![Screenshot 2024-07-07 140432.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2252959/1814f055-0c7c-1e15-aa47-495e7ee234bb.png)

これで、webpackでのreactアプリの立ち上げが成功しました。

# 参考資料
https://qiita.com/hato8899/items/d9613e8bdd0ff470764d
https://zenn.dev/spacemarket/articles/23e5401a074ccc