LoginSignup
3
4

More than 1 year has passed since last update.

docker×webpack×react×typescriptの環境構築(create-react-app不使用)

Last updated at Posted at 2021-09-06

はじめに

この記事ではcreate-react-appに頼ることなくreactの環境を作成する。dockerで構築しているが、手元にnode環境があれば飛ばしても良い。

完成後の構成

環境構築が終わると以下のようなフォルダ構成になる。

.
├── dist
│   ├── index.html
│   └── index.js
├── docker
│   └── node
│       └── Dockerfile
├── node_modules
├── src
│   ├── main.tsx
│   └── sample-component.tsx
└── docker-compose.yml
└── package-lock.json
└── package.json
└── tsconfig.json
└── webpack.config.js

dockerの環境設定

dockerではnodeの環境を構築する。
nodeのDokcefileは以下の通り

Dockerfile
FROM node:16-alpine

WORKDIR /var/www/app

WORKDIRは適当に設定した。nodeのバージョンは16-alpineとしたが、ここから自由に選んで良い(動作確認は16-alpineでしか行ってない)。

docker-compose.ymlは以下の通り

docker-compose.yml
version: "3.8"

services:
  node:
    build: ./docker/node
    tty: true
    volumes:
      - ./:/var/www/app
    working_dir: /var/www/app
    ports:
      - 3000:3000

Dokcerfileとdocker-compose.ymlに分けたが、まとめても問題ない。portsなど細かい設定は任意に変えて良い。これらを設定したら、docker-compose up --build -dでDocker立ち上げると、Dockerのnode環境は完成。

Reactの環境設定

Reactの環境設定はdocker-compose exec node shでnodeのDokcerに入って全て行う(今後行うコマンド全て)。dockerを使わない場合はシェルにそのまま打てば良い。

プロジェクトの初期化

npmプロジェクトの立ち上げとして

npm init -y

と入力する。そうすると

package.json
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

のようなファイルが生成される。立ち上げの際に詳細を設定したい場合は代わりにnpm initと入力して設定する。

必要なパッケージのインストール

今回必要最低限のパッケージとして以下のものをインストールする。

  • webpack: JSモジュールのバンドラー
  • webpack-cli: webpackのCLI
  • typescript
  • ts-loader: typescriptをwebpackで処理するのに必要
  • react
  • react-dom: DOMを管理するもの
  • @types/react: reactの型定義
  • @types/react-dom: react-domの型定義

まず、reactとreact-dom以外は開発専用のパッケージなので

npm i -D webpack webpack-cli typescript ts-loader @types/react @types/react-dom

のようにインストールする。reactとreact-domは普通に

npm i react react-dom

のようにインストールする(nodeのバージョンが低ければオプションに-Sが必要)。今後必要なライブラリがあれば上記のようにインストールするとよい。
このようにインストールすることでpackage.json

package.json
{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/react": "^17.0.20",
    "@types/react-dom": "^17.0.9",
    "ts-loader": "^9.2.5",
    "typescript": "^4.4.2",
    "webpack": "^5.52.0",
    "webpack-cli": "^4.8.0"
  },
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}

のように変更される。その他にもpackage-lock.jsonやnode_modulesが生成される。

typescriptの設定

typescriptの設定はtsconfig.jsonに書く。

tsconfig.json(最小限)
{
    "compilerOptions": {
        "sourceMap": true,
        "target": "ES6",
        "module": "ES2020",
        "jsx": "react",
        "moduleResolution": "node",
        "lib": [
            "ES2020",
            "DOM"
        ]
    }
}

tsconfigの設定は公式が見やすいのでこれを見て変更するとよい。何も考えずに動かす分には上記のものを使用すると良い。

webpackの構成

webpack.config.js
const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/main.tsx",
  output: {
    filename: "main.js",
    path: path.resolve("dist"),
    publicPath: "/",
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: "ts-loader"
      }
    ]
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".json"]
  },
};

この記事ではts,tsxファイルをsrcに置き、その中でもメインファイルをmain.tsxとしているのでentry"./src/main.tsx"となった。また、出力先をdist、コンパイル後のファイル名をindex.jsとしたので、output

{
    filename: "main.js",
    path: path.resolve("dist"),
    publicPath: "/",
},

となった。moduleではts-loaderを使用する条件が書かれており、ts,tsxファイルに対して使用される。resolveはimport文の名前解決のために記述した。

typescriptのビルドコマンド追加

実際に上記で設定通りにts,tsxファイルをコンパイルするコマンドをpackage.jsonのscriptに追加する。

package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack",
    "watch": "webpack -w"
  },

このように追加することでnpm run buildでビルド、npm run watchでホットリロードが可能となる。その他scriptを追加するときはここに追加することとなる。これらのコマンドによってsrc内のmain.tsxdistindex.jsとしてコンパイルされる。

実際に動かしてみる

テンプレートとして静的ファイルであるindex.htmldistに作成する。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <script defer src="./main.js"></script>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>

scriptでコンパイル後のjsファイルを読み込んでいる。<div id="app"></div>を埋め込む場所にReactが反映される(appでなくても良い)。
次にsrcにtypescriptで書かれたreactのファイルを配置する。サンプルとして簡単なファイル用意した。webpack.config.jsのresolveがうまく動いていることを確認するためにtsxのファイルを二個作成した(example-component.tsxがうまくimportされるかを確かめる)。

main.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { SampleComponent } from './sample-component';

class App extends React.Component {
  render() {
    return (
      <div>
        <h1>React Example</h1>
        <SampleComponent name="Counter"/>
      </div>
    );
  }
}

ReactDOM.render(<App/>, document.querySelector('#app'));

最終行のappがindex.htmlのdivのid(app)に対応している。

sample-component.tsx
import * as React from 'react';

interface IProps {
  name: string;
}

export const SampleComponent = (props: IProps): React.ReactElement =>  {
  const [count, setCount] = React.useState<number>(0);

  return (
    <div>
      <h1>{props.name}</h1>
      <div>{count}</div>
      <button onClick={() => setCount(count + 1)}>Count Up</button>
    </div>
  );
}

上記の三つのファイルを作成したのちにnpm run devを行い、./dist/index.jsにファイルが生成されたのを確認したら、index.htmlを開くと
スクリーンショット 2021-09-06 15.27.27.png
こんな感じの簡単なカウンターが現れる。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4