Next.js × TypeScript × Tailwind CSS  × JestとESLint・Prettier設定のBoilterplate紹介

現在開発しているアプリのフロント実装をNext.js × TypeScript・Tailwind CSSでやっています。
今後もしばらくこの構成が鉄板になりそうなので、関連ライブラリのセットアップも含めてボイラープレート化することにしました。

## 環境
- React 17.0.2
- yarn 1.22.11
- Next.js 11.1.0
- TypeScript 4.4.2
- Tailwind 2.2.9
- ESLint 7.32.0
- Prettier 2.3.2
- Jest 27.1.0

##1. Next.jsとTypeScriptでプロジェクトの開始

Next.jsとTailwind CSSのセットでインストールする方法もありますが、TypeScriptとのセットでやった方がTypeScript周りの設定が楽になるのでこちらでいきます。（Tailwind CSSについては後ほど設定していきます。）

```bash
npx create-next-app --ts my-app[アプリ名]
#or
yarn create next-app --ts my-app[アプリ名]
```

参考:

https://nextjs.org/docs/basic-features/typescript

※ちなみに、Tailwind CSSの公式にあるやり方も踏まえ `yarn create next-app -e with-tailwindcss —-ts` みたいに同時にインストールしてみようとしましたが、最初に記述した方しか適用されておらず同時インストールは無理でした。

ついでにsrcフォルダを作成し配下にファイルを移動

```jsx
mkdir src
mv  pages src
mv  components src
mkdir src/lib
```

##2. 絶対パス/パスエイリアスの指定

    ts.configの設定

　※ tsconfig.jsonの変更後はdev serverをリフレッシュしないと反映されないので注意

```bash
{
    "compilerOptions": {
        {...}
        "baseUrl": ".",
        "paths": {
            "@components/*": ["components/*"],
            "@styles/*": ["styles/*"],
            "@pages/*": ["pages/*"],
            "@hooks/*": ["hooks/*"]
        }
    {...}
}
```

こんな感じ

```bash
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "baseUrl": ".",
    "paths": {
        "@components/*": ["components/*"],
        "@styles/*": ["styles/*"],
        "@pages/*": ["pages/*"],
        "@hooks/*": ["hooks/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}
```

参考:

https://nextjs.org/docs/basic-features/typescript#existing-projects

https://blog.antoniolofiego.com/setting-up-a-nextjs-application-with-typescript-jit-tailwind-css-and-jestreact-testing-library

この中身についてはこちらの記事が役に立つ

https://qiita.com/ryokkkke/items/390647a7c26933940470

適宜targetやlibなど設定しておく（本題ではないので飛ばします。興味がある方はご自身で調べてみてください。）

https://book.yyts.org/handson/tsconfig.json-settings

##3. Tailwind CSS と JIT Modeの設定　
※注） 1月24日(月)現在はv3のため設定が異なります。
やり方は3つあり、それぞれ簡略化されて設定が楽になっています。
↓詳しくはこちらをご覧ください。
https://tailwindcss.com/docs/installation


これは色々と設定が必要になります。

```bash
$ npm install -D tailwindcss@latest postcss@latest autoprefixer@latest postcss-cli
#or
$ yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest postcss-cli
```

[https://tailwindcss.com/docs/guides/nextjs#install-tailwind-via-npm](https://tailwindcss.com/docs/guides/nextjs#install-tailwind-via-npm)

tailwind.config.tsとpostcss.config.jsファイルの作成をしていきます。

```bash
npx tailwindcss init -p
```

`postcss.config.js`ファイルは基本的にそのままで大丈夫です。

簡単に中身だけ説明しておくと

```jsx
module.exports = {
  plugins: {
    tailwindcss: {}, //PostCSSのプラグインとしてTailwind CSSを使用する設定
    autoprefixer: {}, //-webkitなどベンダープレフィックスを自動でつけてくれる（様々なブラウザ対応のため）
  },
};
```

`tailwind.config.ts`の中身を設定

JITモードに設定し、不要なCSSを削除するためのpurge設定をする。

purgeとは、ここに設定されているファイル内で使用されているCSSのみをbuild時に使用する最適化手法です。

初期設定は18万行のコードを全て読み込むことになっているため、ファイルサイズが大きくなってしまうのです。

※パス指定はご自身のファイル構造に従ってください。ここが違うとCSSが正しく読み込まれません。

```bash
module.exports = {
    mode: 'jit',
    purge: ['./src/pages/**/*.{js,ts,jsx,tsx}', './src/components/**/*.{js,ts,jsx,tsx}'],
    darkMode: false, // or 'media' or 'class'
    theme: {
        extend: {},
    },
    variants: {
        extend: {},
    },
    plugins: [],
};
```

Tailwind CSSで生成されたCSSを読み込むために styes/Home.module.cssファイルを削除しておきます。

また、styles/global.module.cssはbuild時にtailwind.cssを読み込む際に、動的に反映するファイルとして残しておきましょう。（詳細は後ほど説明します）

そして、styes/tailwind.cssファイルを作成して中身に以下を記述します。

```bash
@tailwind base;
@tailwind components;
@tailwind utilities;
```

もしも@tailwindのルールがないってエラーが出たら

以下の方法で解決

PostCSSのプラグインを導入(VS Codeのみ)

[PostCSS Language Support - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=csstools.postcss)

[How to add a @tailwind CSS rule to css checker](https://stackoverflow.com/questions/47607602/how-to-add-a-tailwind-css-rule-to-css-checker)

詳しくは記事化しました↓

https://qiita.com/hirochan/items/0a2f97d183761645a4be


ついでにTailwind CSSの入力補完をしてくれる、Tailwind CSS IntelliSenseも導入しておきましょう。

https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss

このままではTailwind CSSの記述を変更してもJITモードでリアルタイムに変更されないので、そのための設定をする必要があります。

package.jsonの設定を加える

```bash
{
    ...
    "scripts": {
        "dev": "next dev",
        "build": "next build",
        "start": "next start",
        "lint": "next lint",
        "css:dev": "TAILWIND_MODE=watch postcss src/styles/tailwind.css -o src/styles/globals.css --watch",
        "css:build": "postcss src/styles/tailwind.css -o src/styles/globals.css",
    },
    ...
```

ちょっとわかりづらいかもしれませんが中身はこうなっています。

`TAILWIND_MODE=watch(watchモードにする)`　 

`postcss  [対象となるファイル] -o（outputの略）[アウトプット先のファイル]`

The css:dev script will run PostCSS in watch mode, and Tailwind will listen for changes in our component classes to build new utilities classes on the go. Once everything is done, we can build the final version of the CSS by running our css:build script.

**watchモードとは**
ファイルを監視して変更があったらビルドを再実行する機能のこと。watchモードでは基本的にキャッシュが有効になるため、ビルド時間が短くなる。
例えば、pages/index.tsx内のTailwind CSSを監視して、そこに変更があったときにbuildを改めて走らせてくれる様になります。

では、`npm run dev`もしくは`yarn dev`してlocallhostを立ち上げてください。
Tailwind CSSの記述をしたときにglobals.css（postCSSのファイル）に動的に追記されればOKです。
ブラウザでも動的に変わるか確認しましょう。
変わっていなければ上記の設定の記述に誤りがないか、パスの指定はあっているかなど見直してみてださい。

![スクリーンショット 2021-08-31 14.41.28.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/8fa0b92f-6b56-4a5e-bd59-a41a6250471d/Hnet-image_%281%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210923%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210923T105959Z&X-Amz-Expires=86400&X-Amz-Signature=f9d6834cb421ceb955c30e12e36d71978c4266c8430a778178da271484f3e4ec&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Hnet-image%2520%281%29.gif%22)
・左側のファイル: src/pages/index.tsx
・右側のファイル:globals.css


尚、追加されたCSSの記述はそのまま残ってしまいますが、build時に使わないファイルは消去してくれるので `yarn dev` し直すと不要な記述が消えていることが確認できます。

##4. ESLintとPrettierの導入
**ESLintの導入**
Next.js のバージョン 11 に対応
Next.js では、バージョン 11 から、ESLint がデフォルトで搭載されています。ESLint に関連するインストール済みのパッケージは以下 2 つです。

```bash
  "devDependencies": {
    "eslint": "7.32.0",
    "eslint-config-next": "11.1.0",
    ...
    }
```

Next.js の新規プロジェクト作成時に生成された `.eslintrc.json` は ESLint の設定ファイルを意味しており、デフォルトで eslint-config-next の設定が適用されています（ルールの詳細は後述）

```bash
 // .eslintrc
{
  "extends": ["next", "next/core-web-vitals"]
}
```

次に拡張機能としてESLintを導入します。

![スクリーンショット 2021-08-31 7.49.44.png](https://s3.us-west-2.amazonaws.com/secure.notion-static.com/6f6a1ae2-d9e7-4883-b59c-6adf6e4efd74/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88_2021-08-31_7.49.44.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAT73L2G45O3KS52Y5%2F20210923%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20210923T111413Z&X-Amz-Expires=86400&X-Amz-Signature=28a88d6d6faf3c1275bc30a2d1227680286d63b3d96fd4103b17757c047d6fc6&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22%25E3%2582%25B9%25E3%2582%25AF%25E3%2583%25AA%25E3%2583%25BC%25E3%2583%25B3%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%2583%25E3%2583%2588%25202021-08-31%25207.49.44.png%22)

**VS Code 上でリアルタイムに ESLint で構文解析でき、コードの保守性が高められる様になります。**

しかし、ファイル数が多いとき、**全てのファイルを VS Code で確認するのは大変なため**、対象ファイルを一括で ESLint による構文解析したい場合は、`lint` コマンドを使用する。

```bash
npm run lint
#or
yarn lint
```

また Next.js にデフォルトで搭載された ESLint では、lint コマンドの対象ディレクトリが 以下 3 つに限定されているそうです。

- `pages`
- `lib`
- `components`

そのためおすすめはsrcディレクトリにpagesを含むソースコードを管理して、lintコマンドオプション `—-dir src` でsrcディレクトリ配下のファイルが対象になる。

```bash
#例）
    src
    ├── pages
    │   ├── _app.tsx
    │   ├── api
    │   └── index.tsx
    ├── components
    │   └── hoge.tsx #任意のディレクトリ・ファイル構成
    └── styles
        ├── Home.module.css
        └── globals.css
```

次に、`package.json` の `lint` コマンドに対し、`--dir src` を記述してください。

```package.json
"scripts": {
      ...
      "lint": "next lint --dir src"
      ...
},

```

**Prettierの導入**

チーム開発する際に、コード整形のルールを**コードベースで設定することでばらつきを防ぐことができる。**

**Prettier におけるコード整形のルールを記述する**主な方法は、以下 2 つ

- `.prettierrc` ファイルを作成し、ルールを記述
- `package.json` にルールを記述

省ファイルを意識してpackage.jsonに記述するのがおすすめ

```package.json
      "prettier": {
        "trailingComma": "all",// 末尾のカンマあり
        "tabWidth": 2,// tab の長さは半角スペース 2 つ
        "semi": true,// セミコロンあり
        "singleQuote": true,// シングルクォーテーションに統一
        "jsxSingleQuote": true,//jsx もシングルクォーテーションに統一
        "printWidth": 100 // １ 行の最大文字数 100
      }
```

次に、

以下 2 つのパッケージをインストールしましょう。

- `prettier` 各ファイルをコマンドで、フォーマットできるようにするため
- `eslint-config-prettier` ESLint と Prettier のコード整形がバッティングしないようするため

```bash
npm install -D prettier eslint-config-prettier
#or
yarn add -D prettier eslint-config-prettier
```

さらに.eslintrc.jsonに下記のように設定することでESLintとPrettierのコード整形がバッティングをしない様にできる

```bash
{
  "extends": ["next", "next/core-web-vitals", "prettier"]
}
```

最後に、Prettier でフォーマットするコマンドを `package.json` に記述しましょう。

補足
`--write`: フォーマット整形
`--ignore-path .gitignore`: .gitignore に含まれているファイルはコード整形の対象外
`'./**/*.{js,jsx,ts,tsx,json,css}'"`：対象ファイルの拡張子を指定

```package.json
      "scripts": {
        "lint": "next lint --dir src",
        "lint:fix": "eslint src --ext .js,jsx,.ts,.tsx --fix",
        "format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'"
      }
```

prettierがCLIで効くか
確認する

```bash
npm run format
#or
yarn format
```

##5. JestとReact Testing Libraryのセットアップ

```bash
yarn add -D @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event babel-jest jest jest-dom node-mocks-http ts-jest ts-loader
```

**Project folder 直下に".babelrc"ファイルを作成して下記設定を追加**

`$ touch .babelrc`

```json
 {
    "presets": ["next/babel"]
 }
```

**package.json に jest の設定を追記**

```json
"jest": {
        "testPathIgnorePatterns": [
            "<rootDir>/.next/",
            "<rootDir>/node_modules/"
        ],
        "moduleNameMapper": {
            "\\.(css)$": "<rootDir>/node_modules/jest-css-modules"
        }
    }
```

**package.jsonに test scriptを追記**

```json
 "scripts": {
      ...
      "test": "jest --env=jsdom --verbose"
  },
```

**prettierの設定 : .prettierrcを作成しsettingsでRequire Config + Format On Saveにチェック**

```bash
$ touch .prettierrc
```
.prettierrc

```.prettierrc
    {
        "singleQuote": true,
        "semi": false
    }
```

**Test動作確認**

 **`__tests__`フォルダと`Home.test.tsx`ファイルの作成**

```Home.test.tsx
/**
 * @jest-environment jsdom
 */

import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom'
import Home from '../pages/index'

it('Should render title text', () => {
  render(<Home />)
  expect(screen.getByText('Next.js!')).toBeInTheDocument()
})
```

**yarn test -> テストがPASSするか確認**

```bash
PASS  __tests__/Home.test.tsx
  ✓ Should render hello text (20 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.728 s, estimated 2 s
```

次の様なエラーが出たら、<p>Hello</p>などtextのタグにスペースを開けずにテストしたいテキストのみを記述する。

```bash
TestingLibraryElementError: Unable to find an element with the text: TailwindCSS. 
This could be because the text is broken up by multiple elements. 
In this case, you can provide a function for your text matcher to make your matcher more flexible.
```

これで先程のコマンドをもう一度実行して、パスしていれば完了です。

※とりあえず仮のテストなのでテスト内容によって書き換えが必要です

##最後に

これでようやくできました。色々設定が必要ですが、こうしてまとめておくと今後はプロジェクトのセットアップを省力化できるはずです。

また今回の設定はフロントエンド諸学者である私一個人が調べて導入したものであって、全ての人に当てはまるベストプラクティスではないことを念の為お伝えしておきます。

必要に応じてカスタマイズをしてみてください。

自分も、storybookなどまだ試したことはないけれど入れておきたいライブラリがあるので、確認できたら随時更新していきたいと思います。

また上記の設定で、よりベターな選択肢があれば積極的に情報共有してもらえると嬉しいです。

不明点や誤りがある場合も遠慮なく言っていただければ幸いです。

##参考資料

- hashnode [Setting up a Next.js Application with TypeScript, JIT Tailwind CSS and Jest/react-testing-library][1]
- fwywd [Next.js (TypeScript) に ESLint と Prettier を導入し、コードを綺麗に保とう][2]


[1]:https://blog.antoniolofiego.com/setting-up-a-nextjs-application-with-typescript-jit-tailwind-css-and-jestreact-testing-library
[2]:https://fwywd.com/tech/next-eslint-prettier