TypeScript環境構築 ESLint+Prettier+TailWindCSSの導入

2022年2月12日プログラミング

アイキャッチtyoescript

お久しぶりです。

今回は、自分の備忘録的な内容です。

今回作業する環境は以下の通り

$ node -v
v16.13.0
$ yarn -v
1.22.17

Typescriptのプロジェクト作成

$ yarn create react-app ts-sample --template typescript

作成直後のディレクトリはこちら。(node_modulesは多いので除外しています)

$ cd ts-sample
$ tree -I node_modules                                                                                                                水 12/22 15:04:13 2021
.
├── README.md
├── package.json
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   ├── logo.svg
│   ├── react-app-env.d.ts
│   ├── reportWebVitals.ts
│   └── setupTests.ts
├── tsconfig.json
└── yarn.lock

2 directories, 19 files

ESLintの導入

基本的にはこちらの記事と同じですが、Typescript用に少し変更する必要があります。

まずは、前回と同じようにinitします。

$ yarn eslint --init

対話型の設定で1箇所変更する必要があります。

$ yarn eslint --init                                                                                                                  水 12/22 15:23:39 2021
yarn run v1.22.17
$ ~/ts-sample/node_modules/.bin/eslint --init
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
? Does your project use TypeScript? › No / Yes

こんかいは、TypeScriptを使うので、「Does your project use TypeScript ?」の質問には、「Yes」と回答しましょう。

他は、過去の記事と同じでOKです。

次は必要なパッケージをインストールします。

$ yarn add -D eslint-plugin-react eslint-config-airbnb eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react-hooks

ちゃんと動くか確認します。

$ yarn run eslint --ext tsx src/                                                                                      1007ms  水 12/22 15:30:52 2021
yarn run v1.22.17
$ ~/ts-sample/node_modules/.bin/eslint --ext tsx src/

~/ts-sample/src/App.test.tsx
  3:17  error  Unable to resolve path to module './App'        import/no-unresolved
  3:17  error  Missing file extension for "./App"              import/extensions
  5:1   error  'test' is not defined                           no-undef
  6:10  error  JSX not allowed in files with extension '.tsx'  react/jsx-filename-extension
  8:3   error  'expect' is not defined                         no-undef

~/ts-sample/src/App.tsx
   5:1   error  Function component is not a function expression              react/function-component-definition
   7:5   error  JSX not allowed in files with extension '.tsx'               react/jsx-filename-extension
  11:16  error  `code` must be placed on a new line                          react/jsx-one-expression-per-line
  11:40  error  ` and save to reload.        ` must be placed on a new line  react/jsx-one-expression-per-line

~/ts-sample/src/index.tsx
   4:17  error  Unable to resolve path to module './App'              import/no-unresolved
   4:17  error  Missing file extension for "./App"                    import/extensions
   5:29  error  Unable to resolve path to module './reportWebVitals'  import/no-unresolved
   5:29  error  Missing file extension for "./reportWebVitals"        import/extensions
   8:3   error  JSX not allowed in files with extension '.tsx'        react/jsx-filename-extension
  11:34  error  Missing trailing comma                                comma-dangle

✖ 15 problems (15 errors, 0 warnings)
  4 errors and 0 warnings potentially fixable with the `--fix` option.

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

ずらっとエラーが出たので修正していきましょう。

とりあえずfix

4 errors and 0 warnings potentially fixable with the --fix option.と書いてあるので、自動で直せるものは直してもらいましょう。

$ yarn run eslint --ext tsx src/ --fix                                                                                    1442ms  水 12/22 15:33:49 2021
yarn run v1.22.17
$ ~/ts-sample/node_modules/.bin/eslint --ext tsx src/ --fix

~/ts-sample/src/App.test.tsx
  3:17  error  Unable to resolve path to module './App'        import/no-unresolved
  3:17  error  Missing file extension for "./App"              import/extensions
  5:1   error  'test' is not defined                           no-undef
  6:10  error  JSX not allowed in files with extension '.tsx'  react/jsx-filename-extension
  8:3   error  'expect' is not defined                         no-undef

~/ts-sample/src/App.tsx
  5:13  warning  Unexpected unnamed function                     func-names
  7:5   error    JSX not allowed in files with extension '.tsx'  react/jsx-filename-extension

~/ts-sample/src/index.tsx
  4:17  error  Unable to resolve path to module './App'              import/no-unresolved
  4:17  error  Missing file extension for "./App"                    import/extensions
  5:29  error  Unable to resolve path to module './reportWebVitals'  import/no-unresolved
  5:29  error  Missing file extension for "./reportWebVitals"        import/extensions
  8:3   error  JSX not allowed in files with extension '.tsx'        react/jsx-filename-extension

✖ 12 problems (11 errors, 1 warning)

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

少し減りましたね。(react/jsx-one-expression-per-lineとか)

残りの修正方法を書いていきます。

import/no-unresolved

こちらは、./Appをインポートしようとして出ているエラーです。

これは、拡張子が.tsxに変わったことに起因するエラーで、.tsxも探してくれるように設定する必要があります。

設定箇所は、.eslintrc.yml

参考:既存プロジェクトを TypeScript に移行する際の ESLint の対応

settings:
  import/resolver:
    node:
      extensions:
        - '.js'
        - '.jsx'
        - '.ts'
        - '.tsx'

こうすることで、指定した拡張子も探してくれてエラーが出なくなります。

import/extensions

次の記述をrulesに追加します。

参考:eslint-plugin-importでTypeScriptのimport問題を解決する

rules: {"import/extensions":[1, {".js", ".jsx", ".ts", ".tsx"}]}

no-undef

App.test.ts内で使われている関数の定義が見つからないといっていますね。

デフォルトのESLintでは、定義されている場所を見つけることができないので、envブロックに追記してあげます。

参考:Environment key “jest/globals" is unknown

env:
  browser: true
  es2021: true
  jest: true # 追加

react/jsx-filename-extension

こちらは、.tsxという拡張子がESLintで許可されていないため発生しています。

以下をrulesに追加して、.ts.tsxを許可してあげましょう。

参考:JSX not allowed in files with extension '.tsx’eslint(react/jsx-filename-extension)

'react/jsx-filename-extension': [2, { 'extensions': ['.js', '.jsx', '.ts', '.tsx'] }]

最終的な.eslintrc.yml

こうなります。

env:
  browser: true
  es2021: true
  jest: true
extends:
  - plugin:react/recommended
  - airbnb
settings:
  import/resolver:
    node:
      extensions:
        - '.js'
        - '.jsx'
        - '.json'
        - '.ts'
        - '.tsx'
parser: '@typescript-eslint/parser'
parserOptions:
  ecmaFeatures:
    jsx: true
  ecmaVersion: 12
  sourceType: module
plugins:
  - react
  - '@typescript-eslint'
rules: {"import/extensions":[2, {".js", ".jsx", ".ts", ".tsx"}], 'react/jsx-filename-extension': [2, { 'extensions': ['.js', '.jsx', '.ts', '.tsx'] }],}

ESLintを実行した結果は以下の通りです。

$ yarn run eslint --ext tsx src/
yarn run v1.22.17
$ /Users/tohi/RaiseTech/react/task/task11/ts-sample/node_modules/.bin/eslint --ext tsx src/

/Users/tohi/RaiseTech/react/task/task11/ts-sample/src/App.tsx
  5:13  warning  Unexpected unnamed function  func-names

✖ 1 problem (0 errors, 1 warning)

✨  Done in 4.61s.

警告は残りましたが、とりあえずOKです!

このあと、Prettierの導入も行いましたが、過去記事と同じなので割愛します。

TailWindCSSの導入

リッチなUIを提供するライブラリです。

cracoの導入

今回、$ yarn create react-appでプロジェクトを作っているので、色々細かい調整をするのにejectしないといけません。

cracoを使うと、ejectせずに設定を上書きすることができます。

$ yarn add -D @craco/craco

cracoを使うと、create react-appで作成したプロジェクトをejectせずにいじれます。

インストールしたらpackage.jsonのscriptsを書き換えます。

{
  "name": "ts-template",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^12.0.0",
    "@testing-library/user-event": "^13.2.1",
    "@types/jest": "^27.0.1",
    "@types/node": "^16.7.13",
    "@types/react": "^17.0.20",
    "@types/react-dom": "^17.0.9",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "5.0.0",
    "typescript": "^4.4.2",
    "web-vitals": "^2.1.0"
  },
// ここから
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },
// ここまで
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "autoprefixer": "^10.4.0",
    "eslint-config-airbnb": "^19.0.2",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-jsx-a11y": "^6.5.1",
    "eslint-plugin-react": "^7.27.1",
    "eslint-plugin-react-hooks": "^4.3.0",
    "postcss": "^8.4.5",
    "prettier": "^2.5.1",
    "tailwindcss": "^3.0.7"
  }
}

次は、craco.config.jsを作成します。

$ touch craco.config.js

内容は以下の通りです。

module.exports = {
  style: {
    postcssOptions: {
      plugins: [
        require('tailwindcss'),
        require('autoprefixer'),
      ],
    },
  },
}

Tailwindのインストール

まずは必要なパッケージのインストールしてinitします。

$ yarn add -D tailwindcss postcss autoprefixer
$ npx tailwindcss init -p
Created Tailwind CSS config file: tailwind.config.js
Created PostCSS config file: postcss.config.js

実行すると、tailwind.config.jspostcss.config.jsが作成されます。

作成されたtailwind.config.jsにpurgeオプションを追加します。

buildする時に余計なスタイルを含めないようにしてくれるようです。

module.exports = {
  content: [],
  purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
  theme: {
    extend: {},
  },
  plugins: [],
};

最後に、./src/index.csstailwnidを追加します。

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

code {
  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
    monospace;
}

参考:tailwind2.0 + react + typescript 環境構築

プログラミング

Posted by kotaro