Typescript + React 環境構築

# create-react-appを使わずにReactの環境構築

##### まっさらの状態からReactを使ってブラウザで「Hello World」を表示する

※npmではなくyarn
なので`yarn init`でlockファイルを作成

## Webpack
`yarn add -D webpack webpack-cli webpack-dev-server html-webpack-plugin dotenv-webpack`

## babel
`yarn add -D @babel/core @babel/runtime @babel/plugin-transform-runtime @babel/preset-env babel-loader`

## React
`yarn add react react-dom`
`yarn add -D @babel/preset-react`

## Typescript
`yarn add -D typescript @babel/preset-typescript @types/react @types/react-dom`

## CSS系
`yarn add style-loader css-loader`

## tsconfig.jsonの作成
`yarn run tsc --init`

    {
      "compilerOptions": {
    "typeRoots": ["types", "node_modules/@types"],//pngの型がないとエラーが起きるので後付け
    "jsx": "react",
    "target": "ES2021",
    "lib": [
      "ES2021",
      "dom"
    ] ,

    /* Modules */
    "module": "commonjs",
    "moduleResolution": "node",
    "resolveJsonModule": true ,

    /* Emit */
    "outDir": "./dist",
    "noEmit": true,
    "downlevelIteration": true,

    /* Interop Constraints */
    "isolatedModules": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true ,

    /* Type Checking */
    "strict": true,
    "noImplicitAny": true ,
    "strictNullChecks": true ,
    "strictFunctionTypes": true ,
    "strictBindCallApply": true ,
    "strictPropertyInitialization": true ,
    "noImplicitThis": true ,
    "useUnknownInCatchVariables": true ,
    "alwaysStrict": true ,
    "noUnusedLocals": true ,
    "noUnusedParameters": true ,
    "exactOptionalPropertyTypes": true ,
    "noImplicitReturns": true ,
    "noFallthroughCasesInSwitch": true ,
    "noUncheckedIndexedAccess": true ,
    "noImplicitOverride": true ,
    "noPropertyAccessFromIndexSignature": true ,
    "allowUnusedLabels": true ,
    "allowUnreachableCode": true 
    },
    "exclude": ["node_modules"],
    "include": ["src/**/*"]
    }

## png型エラーしないように自作

 src > typesフォルダ　> index.d.ts

    declare module "*.png"
    declare module "*.jpeg"


## webpack.config.jsの作成

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const Dotenv = require("dotenv-webpack");

    module.exports = {
      mode: "development",
      entry: path.resolve(__dirname, "./src/index.tsx"), // 始まるところ
      output: {
        path: path.resolve(__dirname, "dist"), // distを本番環境
        filename: "index.js", // jsに変換
      },
      resolve: {
        modules: [path.resolve(__dirname, "node_modules")],
        extensions: [".ts", ".tsx", ".js", ".css"],
      },
      module: {
        rules: [
          {
            test: [/\.ts$/, /\.tsx$/],

            use: [
              {
                loader: "babel-loader",
                options: {
                  presets: [
                    "@babel/preset-env",
                    "@babel/preset-react",
                    "@babel/preset-typescript",
                  ],
                  plugins: ["@babel/plugin-transform-runtime"], // fetchを使いたかったができなかったため後から追加した
                },
              },
            ],
          },
          {
            test: /\.css$/,
            use: ["style-loader", "css-loader"],
            exclude: /src/,
          },
          {
            test: /\.png/,
            type: "asset/resource",
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "./src/index.html"),
        }),
        new Dotenv(),
      ],
      devServer: {
        port: 8111, // サーバー側とPORTが被らないように指定
        static: {
          directory: path.join(__dirname, "dist"),
        },
        historyApiFallback: true,
        host: "0.0.0.0",
        allowedHosts: "all",
      },
    };


## index.htmlの作成

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>タイトル</title>
      </head>
      <body>
        <div id="root"></div>
      </body>
    </html>

※src > index.html

## index.tsxの作成

    import React from "react"
    import ReactDOM from "react-dom"
    import App from "./app"

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

※src > index.tsx

## app.tsx
    import React from "react"

    const App = () => <h1>Hello World</h1>
     export default App

※src > app.tsx

## 最後に
1. package.jsonのscriptsに`"start": "npx webpack serve --config webpack.config.js"`
を書き込む
1. `yarn start`
1. ブラウザで`http://localhost:8111`にアクセスする

Hello Worldが表示される！

## 参考記事
https://enjoyworks.jp/tech-blog/6889

https://enjoyworks.jp/tech-blog/7337

https://qiita.com/chocomint_t/items/4bc57945bce081922582

https://webpack.js.org/guides/asset-modules/

https://note.kiriukun.com/entry/20200704-regeneratorRuntime-is-not-defined

https://numb86-tech.hatenablog.com/entry/2018/03/03/131414