react.js開発環境構築
1. 目的
-
react.js
+ TypeScript
のプロジェクトの作成
- ローカル環境を汚染したくないので環境はDockerコンテナで完結
- ソースコードはボリュームを介してコンテナと共有
-
create-react-app
は使わない方針
2. 環境
- 環境はこんな↓感じ(Ubuntu20.04で開発していく)
- Docker内で完結するのでOSは問わないはず
$ uname -srvmpio
Linux 5.8.0-59-generic #66~20.04.1-Ubuntu SMP Thu Jun 17 11:14:10 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
$ docker -v
Docker version 20.10.7, build f0df350
$ docker-compose -v
docker-compose version 1.26.0, build d4451659
3. プロジェクト初期構成
.
├── .env
├── .gitignore
├── Dockerfile
├── docker-compose.yaml
└── package.json
$ touch .env .gitignore Dockerfile docker-compose.yaml package.json
4. 開発用のコンテナ(node.js)作成
Dockerfile
FROM node:16.14
WORKDIR /app
COPY . /app
RUN yarn install
CMD ["yarn", "start"]
- 2021/07時点の最新リリースであるv16のイメージを使用
- 適当にWorkingDirを作って、プロジェクトディレクトリを丸ごとコピー
-
yarn install
で依存ライブラリを取得
docker-compose.yaml
-
docker-compose.yaml
の内容は以下の通り
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
env_file:
- .env
ports:
- ${PORT}:${PORT}
volumes:
- .:/app
.env
PORT=8080
NODE_MODE=development
.gitignore
node_modules
dist
.env
package.json
-
package.json
の内容は以下の通り
-
yarn init
から作成してもよい
{
"name": "react-example",
"version": "1.0.0",
"private": true,
"scripts": {
"test": "echo hello"
}
}
コンテナの動作確認
- コンテナをビルドして、
npm
コマンドとyarn
コマンドが動くか確認
$ docker-compose build
$ docker-compose run --rm app npm -v
$ docker-compose run --rm app yarn -v
5. プロジェクトセットアップ
ライブラリインストール
-
react.js
、typescript
、webpack
、jest
、eslint
、prettier
をインストール
$ yarn add react \
react-dom \
typescript \
webpack \
webpack-cli \
webpack-dev-server \
html-webpack-plugin \
ts-loader \
jest \
eslint \
prettier \
@types/jest \
@types/node \
@types/react \
@types/react-dom \
@typescript-eslint/eslint-plugin \
@typescript-eslint/parser
各種設定ファイル作成
$ touch webpack.config.js \
tsconfig.json \
jest.config.js \
eslintrc.json \
.eslingignore \
.prettierrc
package.jsonのscriptsセクションを更新
-
package.json
のscripts
セクションに↓を追加
"scripts": {
"test": "jest",
"start": "webpack-dev-server",
"build": "webpack",
"fmt": "prettier --write ./src/*.{js,json,ts,tsx}"
},
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
})
module.exports = {
mode: process.env.NODE_MODE,
entry: path.join(__dirname, 'src/index.tsx'),
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
}
]
},
resolve: {
extensions: ['.ts', '.tsx', '.js' , '.json'],
},
devServer: {
static: {
directory: path.join(__dirname, "dist"),
},
open: true,
port: process.env.PORT
},
plugins: [
htmlPlugin
]
}
tsconfig.json
{
"compilerOptions": {
"baseUrl": "src",
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"exclude": ["node_modules"],
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
jest.config.js
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
globals: {
"ts-jest": {
tsconfig: './tsconfig.test.json'
}
}
};
eslintrc.json
{
"extends": "eslint:recommended",
"rules": {
}
}
.eslingignore
node_modules/
.prettierrc
{
"arrowParens": "always",
"bracketSpacing": true,
"endOfLine": "lf",
"htmlWhitespaceSensitivity": "css",
"jsxBracketSameLine": false,
"jsxSingleQuote": false,
"printWidth": 120,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false
}
6. ソースコード配置
index.tsx配置
-
src
ディレクトリを作成し、index.tsx
を作成
$ mkdir src
$ cd src
$ touch index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
const App = () => {
return <div>Hello World.</div>
}
ReactDOM.render(<App />, document.getElementById('app'))
index.html配置
-
public
ディレクトリを作成し、index.html
を作成
$ mkdir public
$ cd public
$ touch index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>react typescript app</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
7. 開発サーバ起動
$ docker-compose up
- ここまでで最小構成の
react.js
プロジェクトが作成されたので、プロジェクトで使用するライブラリを適宜追加していくことになる
8. 補足
リポジトリからクローンしてきた場合に行うこと
- 上述の手順で環境を構築した場合はプロジェクトディレクトリに
node_modules
が存在するので問題ないが、リポジトリからクローンしてきた場合はnode_modules
が存在しない為、コンテナ起動時にエラーが発生する
- リポジトリからクローンしてきた場合など
node_modules
が存在しない場合は、コンテナを起動する前にyarn install
を実行しておく必要がある
$ docker-compose run --rm app yarn install
$ docker-compose up -d
ライブラリを追加したい場合
-
docker-compose (run|exec) app yarn add xxx
でインストールする
- コンテナが停止している場合は
run
、起動している場合はexec
# コンテナが停止している場合
$ docker-compose run --rm app yarn add ${インストールしたいライブラリ}
# コンテナを起動している場合
$ docker-compose exec app yarn add ${インストールしたいライブラリ}