TL;DR
- webpack, typescript, react, prettier, eslint, airbnbを使ってreactの最新開発環境を構築する。
基本知識
下記のポストと文書を参考にしてこの記事を作成しました。
- https://ics.media/entry/16329/#webpack-ts-react
- https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
- https://github.com/typescript-eslint/typescript-eslint#how-do-i-configure-my-project-to-use-typescript-eslint
- https://prettier.io/docs/en/integrating-with-linters.html#use-both
- https://medium.com/dubizzletechblog/setting-up-prettier-and-eslint-for-js-and-react-apps-bbc779d29062
- https://medium.com/@joshuacrass/javascript-linting-and-formatting-with-eslint-prettier-and-airbnb-30eb746db862
他のものはともかく1と2は目を通してください。
1と2のポストでは最小構成で説明しているので、自分なりに必要だと思った構成を3~6まで参考にして追加しました。
step by stepでコマンドを実行する形になっています。
プロジェクトの生成
Reactだけではないですが、プロジェクト単位でフォルダを作ってその中で必要なライブラリを設置し開発作業(コーディング)を行うのは基本です。
mkdir webpack-ts-react
cd webpack-ts-react
npm init -y
mkdir dist
mkdir src
srcはソースフォルダで、distはソースファイルをcompileしたファイルが保存されるフォルダになります。
dist以外にbuildやpublicなどの名前でフォルダを作る場合もあります。
webpackのインストール
webpackはデファクトスタンダードとして使われているモジュール(ライブラリ)バンドラーです。
npm i -D webpack webpack-cli webpack-dev-server
- webpack
- core library
- webpack-cli
- webpackのcommand line interface
- webpack-dev-server
- webpackのdevelopment server
- ソースコードの変更事項をブラウザにすぐ反映してくれる。
typescriptのインストール
npm i -D typescript ts-loader
- typescript
- core library
- ts-loader
- webpackでtypescriptをcompileするために必要
reactのインストール
npm i -S react react-dom @types/react @types/react-dom
reactとreact-domでtypescriptの型定義1を使いたいので、@types/reactと@types/react-domも一緒にインストールします。
prettierのインストール
prettierはcode formatting(コード整形)を行ってくれるライブラリーです。
eslintも「eslint --fix」でcode formattingができますが、prettierの方がeslintより優れていて、eslintとprettierを併用して使うケースが多いです。
lintingはeslintを、code formattingはprettierを使うイメージです。
npm i -D prettier eslint-config-prettier eslint-plugin-prettier pretty-quick
-
prettier
- core library
-
eslint-config-prettier
- prettierと競合するeslintのルールを無視する。
-
eslint-plugin-prettier
- eslintのルールでprettierを実行する。
-
pretty-quick
- 変更されたファイルだけprettierを実行する。
.eslintrc.jsonに以下の内容を追記します。
eslintとprettierを一緒に使うための設定です。
{
"plugins": ["prettier"],
"extends": ["plugin:prettier/recommended"],
"rules": {
"prettier/prettier": "error"
}
}
eslint + airbnb
eslintのルールを拡張したairbnbのルール(コードコンベンション)を使います。
eslint-config-airbnbの最新バージョンの依存性パーケージを確認してください。
npm info "eslint-config-airbnb@latest" peerDependencies
{
eslint: '^4.19.1 || ^5.3.0',
'eslint-plugin-import': '^2.18.0',
'eslint-plugin-jsx-a11y': '^6.2.3',
'eslint-plugin-react': '^7.14.2'
}
eslint-config-airbnbとその依存性パーケージをインストールします。
npm i -D eslint-config-airbnb eslint@5.3.0 eslint-plugin-import eslint-plugin-jsx-a11y@6.2.3 eslint-plugin-react
npm 5+以上を使っている場合は下記のshortcutも使えます。
npx install-peerdeps --dev eslint-config-airbnb
.eslintrc.jsonに以下の内容を追記します。
{
"extends": ["airbnb"]
}
reactを使わない場合は、airbnbの代わりにairbnb-baseを使います。
eslint + typescript
typescriptではlintingのためにtslintというものがあります。
eslintの方が幅広いルールを提供しているので、tslintではないeslintを使います。
typescriptとeslintを一緒に使うためには下記のパーケージをインストールする必要があります。
npm i -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
.eslintrc.jsonに以下の内容を追記します。
eslintとtypescriptを一緒に使うための設定です。
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": ["plugin:@typescript-eslint/recommended"]
}
typescriptを使わない場合は、parserとしてbabel-eslintを使います。
tsconfig.json
typescriptの設定ファイルです。
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"target": "es5",
"module": "es2015",
"jsx": "react",
"moduleResolution": "node",
"lib": [
"es2019",
"dom"
]
},
"include": [
"src/**/*"
]
}
compileされたソースコードの出力場所はdistで、
sourceMapをtrueにしたので、complieされたソースコードは圧縮されずに保存されます。
targetをes5にしたので、es5でcomplieされます。
includeにはソースフォルダを指定します。これで自分が作成したソースコードも補完に利用されます。
excludeは設定しない場合、デフォルトでnode_modulesが設定されます。
tsconfig.jsonの詳細が知りたい場合は下記の文書を参照してください。
.eslintrc.json
ここまでして完成された.eslintrc.jsonのファイルです。
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"project": "./tsconfig.json",
"useJSXTextNode": true
},
"plugins": ["@typescript-eslint", "prettier"],
"extends": [
"airbnb",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
"plugin:prettier/recommended"
],
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"prettier/prettier": "error",
"max-len": ["error", {"code": 100}],
"prefer-promise-reject-errors": ["off"],
"react/jsx-filename-extension": ["off"],
"react/prop-types": ["off"],
"no-return-assign": ["off"]
}
}
ルール(コードコンベンション) | ライブラリー |
---|---|
"airbnb" | eslint-config-airbnb, eslint, eslint-plugin-import, eslint-plugin-jsx-a11y, eslint-plugin-react |
"plugin:@typescript-eslint/recommended" | @typescript-eslint/eslint-plugin |
"prettier/@typescript-eslint" | eslint-config-prettier |
"plugin:prettier/recommended" | eslint-plugin-prettier |
rulesのところはご自分の設定に合わせてください。
.prettierrc
prettierの設定ファイルです。
option名を見れば大体わかると思うので、optionの説明は割愛します。
{
“printWidth”: 100,
“trailingComma”: “all”,
“tabWidth”: 2,
“semi”: true,
“singleQuote”: true
}
package.json
ここまでして完成されたpackage.jsonのファイルです。
{
"name": "webpack-ts-react",
"version": "1.0.0",
"description": "webpack + typescript + reactの最小構成",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server",
"build": "webpack",
"watch": "webpack -w",
"lint": "eslint src -c .eslintrc.json --ext ts,tsx; exit 0",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^1.13.0",
"babel-eslint": "^10.0.2",
"eslint": "^5.3.0",
"eslint-config-airbnb": "^17.1.1",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.0",
"eslint-plugin-react": "^7.14.3",
"prettier": "^1.18.2",
"pretty-quick": "^1.11.1",
"ts-loader": "^6.0.4",
"typescript": "^3.5.3",
"webpack": "^4.38.0",
"webpack-cli": "^3.3.6",
"webpack-dev-server": "^3.7.2"
},
"dependencies": {
"@types/react": "^16.8.23",
"@types/react-dom": "^16.8.5",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}
webpack.config.js
webpackの設定ファイルです。
module.exports = {
devtool: 'source-map',
// モード値をproductionに設定すると最適化される状態で、
// developmentに設定するとソースマップ有効でJSファイルが出力される。
mode: 'development',
// メインとなるjavascriptファイル(エントリーポイント)
entry: './src/main.tsx',
// ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: 'main.js'
},
module: {
rules: [
{
// 拡張子.tsもしくは.tsxの場合
test: /\.tsx?$/,
// TypeScriptをコンパイルする
use: 'ts-loader'
}
]
},
// import文で.tsや.tsxファイルを解決するため
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json']
},
devServer: {
contentBase: './dist',
historyApiFallback: true,
inline: true,
hot: true,
port: 5000,
open: true
}
}
動作確認
サンプルコードはここを参照しました。
npm run lint
> webpack-ts-react@1.0.0 lint /Users/devtopia/apps/study/js/webpack-ts-react
> eslint src -c .eslintrc.json --ext ts,tsx; exit 0
/Users/devtopia/apps/study/js/webpack-ts-react/src/main.tsx
5:1 error Component should be written as a pure function react/prefer-stateless-function
6:3 error Missing accessibility modifier on method definition render @typescript-eslint/explicit-member-accessibility
6:9 warning Missing return type on function @typescript-eslint/explicit-function-return-type
/Users/devtopia/apps/study/js/webpack-ts-react/src/sub-component.tsx
12:29 warning Unexpected any. Specify a different type @typescript-eslint/no-explicit-any
19:22 warning Missing return type on function @typescript-eslint/explicit-function-return-type
20:5 warning Unexpected console statement no-console
23:14 error Must use destructuring state assignment react/destructuring-assignment
23:14 error Use callback in setState when referencing the previous state react/no-access-state-in-setstate
27:3 error Missing accessibility modifier on method definition render @typescript-eslint/explicit-member-accessibility
27:9 warning Missing return type on function @typescript-eslint/explicit-function-return-type
30:14 error Must use destructuring props assignment react/destructuring-assignment
31:15 error Must use destructuring state assignment react/destructuring-assignment
32:9 error Missing an explicit type attribute for button react/button-has-type
✖ 13 problems (8 errors, 5 warnings)
-
typescriptを使う場合もjavascriptのライブラリを使います。しかし、javascriptにはtypescriptのように型定義が存在しないので、そのままだとcompileできない場合があります。そこで、使うのが型定義ファイルです。 ↩