LoginSignup
18
18

More than 1 year has passed since last update.

LintとTestをフル活用したNext.jsのテンプレ作成ガイド

Last updated at Posted at 2021-11-24

1...2の...ポカン!

image.png

私は個人開発で小さなアプリを何度もこさえることがありますが、
その度に必要なパッケージをインストールしたり、設定ファイルを書くのは面倒です。

しかも、私の脳は1つ新しいことを学ぶと1つ前のものは忘れるという仕様なので、
その都度調べるということが起きてしまいます。

私の脳みそを改造できたらいいのですが、
そんなことできるはショッカーダイジョーブ博士ぐらいです。

なので代替案としてテンプレを作っておいて、いつでもそれを使えるようにしておこう!
という目論見で開かれたのがこの会です。

参加者は私一人です。
それではいきましょう。

Nextにパッケージ何入れようかサミット

厳重な審査の結果、今回の雛形に選ばれたのは以下のパッケージです。
後の章でこれらの説明や、導入方法について記述します。
また、これら以外にもいくつかの細かいパッケージも必要になってきますが、ここでの記載は省きます。

パッケージ名 説明 備考
Typescript みんな大好きTypescript
ESLint js/tsのファイルの書き方を監督してくれる人 リント用
Prettier コードを綺麗にしてくれる人 整形用
StyleLint スタイルの書き方を監督してくれる人 リント用
CommitLint commit messageの書き方に口出ししてくる人 リント用
Sass cssをsass形式で描けるようにしてくれる人
MaterialUI コンポーネントの詰め合わせパックの人
DependBot パッケージのバージョンを新しくしてくれる人
Jest js/tsのテストをできるようにしてくれる人 テスト用
StoryBook 見た目のテストとかカタログ(jsDoc見た目版みたいな)を作る人 テスト用

惜しくも今回含まれなかった方々

ReduxRecoilApploClientとかの「データをメモリ保存する勢」
firebaseとかaxiosとかの「非同期通信を簡単に実装します勢」も含めませんでした。

自分でサーバーを実装するか? GraphQLを使うのか? RESTだけでいくのか?などの要因によって何をいれたいかは変わってくるので、ここら辺は雛形にいれなくてもいいかなと思ったからです。

また、tailwindcssstyled componentも含めませんでした。
個人的にCSS moduleが好きなので、そちらを採用したいという結論がサミットでは出たためです。

ディレクトリ構成について

今回はAtomicデザインを採用します。
この構成について賛否両論ありますが、詳しい議論について私はあまり知らないので脳死でAtomicにしました。
ディレクトリはこんな感じにしています。

src
├── pages
│   ├── _app.tsx
│   ├── api
│   └── index.tsx
├── components
│   └── atoms
│   └── molecules
│   └── organisms
│   └── templates
└── styles
    ├── Home.module.css
    └── globals.css

因みに、Nextはデフォルトでsrcディレクトリがないので、それを追加する必要があります。
(必要はない。私が追加したいだけ)

この先読むのが面倒くさい方へ

ここにコードがあるから、これをcloneして貰えばこのパッケージで開発を進めることができます。

StoryBookの導入だけ私が試すとvulnerabilitiesが出てしまって直せていないので、
StoryBook込みのものはwidth_storybookというブランチに取り分けてあります。

プロジェクトの作成

では実際にこれらを追加して行きましょう。
以下のコマンドでTypeScriptをデフォルトとするNext.jsのプロジェクトを作成します。
「すでに作成済みのプロジェクトにパッケージを追加したい」という人は飛ばして下さい。

npx create-next-app --typescript

実行したらプロジェクトの名前はどうするよ?って聞かれると思うので、
いい感じの名前をつけておきましょう。

image.png

srcディレクトリの作成

プロジェクトが作成できたら、次にディレクトリ構造を整理しておきましょう。
前述の通り、Next.jsはデフォルトでsrcディレクトリが存在しないので作ってあげましょう。

と言ってもsrcという名前のディレクトリを作って、その中にstylesとかpagesとか入れるだけですね。componentsというディレクトリも作っておくといいでしょう。

ディレクトリ構成についてはこれでOKです。
次にESLintの設定をして行きましょう。

ESLintの設定

Next.jsではver.11からデフォルトでESLintが備えられるようになった
ので特にインストールする必要はありません

なので、ESLintの導入の手順は以下のようになります。

  1. ESLintのパッケージのインストール(インストール済だから不要)
  2. srcディレクトリ配下もチェックするように設定
  3. 行末にセミコロン;がないとエラーになるように設定
  4. import文を絶対パスで記述するルールの追加
  5. import文の記述順をアルファベット順にする
  6. ESLintの整形コマンドを登録しておく
  7. (おまけ)VScodeのESLint拡張機能を追加する

srcディレクトリ配下もチェックするように設定

lintのコマンド実行時にデフォルトではsrcファイルディレクトリ配下は無視されます。
このままではsrcが可哀想なので、仲間に入れてあげましょう。
package.jsonscriptsにある"lint"の部分を以下のようにするだけです。

参考:Basic Features: ESLint | Next.js

package.json
  "scripts": {
    ・・・
    // 「--dir src」を追加
    "lint": "next lint --dir src"
  }

行末にセミコロン;がないとエラーになるように設定

行末にセミコロンがなくても動きますが、「必ず全部つける」で統一しておいた方が
綺麗なのでセミコロンが無ければ、ESLintに怒ってもらうように設定します。

[ESLintのルール](https://eslint.org/docs/rules/](https://eslint.org/docs/rules/)

eslintrc.json
{
  ・・・
  // 追記
  "rules": {
    // セミコロンない場合、エラー出力
    "semi": ["error", "always"]
  }
}

import文を絶対パスで記述するルールの追加

import文を記述する時に相対パスじゃなくて絶対パスで書きたいですよね。

ESLintで絶対パスのimportに制限するルールを追加するには
.eslintrc.jsonに記述するだけでです。

eslintrc.json
  "rules": {
    "no-restricted-imports": [
      "error",
      {
        "patterns": ["./", "../"]
      }
    ]
  }

ついでに、以下のように絶対パスを@/...と書けるように設定しておきましょう。

import styles from '../styles/Home.module.css'; // こうじゃなくて
import styles from '@/styles/Home.module.css'; // こう

tsconfig.jsonに以下のように記述してあげれば
@/...src/...と解釈してくれるようになります。

tsconfig.json
"compilerOptions": {
    ・・・
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
}

importの順番をアルファベット順にする

些細なことですが、importの順番もアルファベット順だったら
気持ちいい気がするので、ESLintにお願いしておきましょう。
.eslintrc.jsonを以下のようにするだけです。

eslintrc.json
{
  "extends": [
    ・・・
    // 追記
    "plugin:import/recommended",
    "plugin:import/warnings"
  ],
  "rules": {
    ・・・
    // import の順番をルール化
    "import/order": [
      "error",
      {
        "alphabetize": {
          "order": "asc"
        }
      }
    ]
  }
}

ESLintの整形コマンドを登録しておく

ESLintに従ってコードを整形してくれるコマンドをpackage.jsonに追加しておきましょう。

commit時に自動でチェック・修正してくれる設定は後述。 その際にここで定義したコマンドを呼ぶようにするので、 ここで登録しておくのがいいかも。

package.json
  "scripts": {
    ・・・
    // 以下を追加
    "lint:fix": "eslint src --ext .js,jsx,.ts,.tsx --fix"
  }

これでnpm run lint:fixを実行すれば、綺麗に整形されるようになっているはずです。

(おまけ)VScodeのESLint拡張機能を追加する

VSCodeの場合は以下の拡張機能を入れるとリアルタイムでLintが適用され、
書き方が規則に則っていない場合には警告やエラーが表示されるようになります。

https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565905/715a516c-9974-823a-21f5-82dea7b39121.png

Prettierの設定

Prettierはコードを綺麗に整形してくれる人です。
同じくESLintも綺麗にする能力に長けていますが、
Prettier先生にしかできない整形があったりするらしいので、この先生も入れます。

Prettier導入の手順は以下の通り。

  1. Prettierに必要なパッケージをインストール
  2. PrettierESLintが共存できるような設定の追加
  3. (おまけ) VScodeのPrettierの拡張機能を追加
  4. (おまけ)Prettier拡張機能用の設定を記述

Prettierに必要なパッケージをインストール

さて、Prettierをインストールして行きます。
因みにESLintとPrettierは基本仲良しですが、お互いのこだわりが異なる部分では
喧嘩するらしいので、喧嘩しないように気を遣ってくれるeslint-config-prettierも入れておきます。

npm install -D prettier eslint-config-prettier

PrettierESLintが共存できるような設定の追加

PerttierESLintが喧嘩しないように、設定を追加して行きます。
.eslintrc.jsonextendsの部分にprettierを加えてあげましょう。

eslintrc.json
"extends": ["next/core-web-vitals", "prettier"]

これだけです。

(おまけ) VScodeのPrettierの拡張機能を追加

VScodeを使っている人は、Prettierの拡張機能を導入しておくことで、
保存時に自動的に整形してくれるようになります。

image.png

(おまけ)Prettier拡張機能用の設定を記述

VScodeのPrettier拡張機能を入れたら、package.jsonにその設定を書きます。
Prettierにおける設定はVSCode上でも設定できます
ですが、チーム開発する場合を考慮して、コードに残しておくのがいいと思います。

package.jsonが汚くなるのがいやという人は
.prettierrcという設定ファイルを別途書いてもいいです。

package.json
・・・
  "prettier": {
    "trailingComma": "all",
    "tabWidth": 2,
    "semi": true,
    "singleQuote": true,
    "jsxSingleQuote": true,
    "printWidth": 100
  }

上記コードの各プロパティの説明

プロパティ名 説明
trailingComma 末尾のカンマあり
tabWidth tabの長さを定義
semi セミコロンの有無
singleQuote シングルクォーテーションに統一するか
jsxSingleQuote jsx もシングルクォーテーションに統一するか
printWidth 1行の最大文字数

Prettierの設定はここまでです!
お疲れ様です!

Stylelintのインストール

Stylelintとは、スタイル(css, scss, sass)の書き方をチェックし、整形してくれる人です。
Stylelintを導入するステップは以下の通りです。

  1. Stylelintの必要パッケージをインストール
  2. Stylelintの設定ファイルを記述する
  3. Stylelintのチェックコマンド・修正コマンドを追加する
  4. (おまけ)VScodeの拡張機能を追加する

Stylelintのインストール

以下の3つをインストールします。

パッケージ名 説明
Stylelint スタイルファイルの構文解析エンジン
stylelint-config-standard Google's CSS Style Guide や Airbnb's Styleguide などを含むスタイルガイドラインのルール
stylelint-order CSS プロパティをアルファベット順に並べるためのルール

コマンドは以下の通り。

npm install -D stylelint stylelint-config-standard stylelint-order

Stylelintの設定ファイルを記述する

次に.stylelintrc.jsonという名前でファイルを作成しましょう。
このファイルに以下の設定を記述します。

stylelintrc.json
{
  "plugins": ["stylelint-order"],
  "extends": ["stylelint-config-standard"],
  "rules": {
    "at-rule-no-unknown": [
      true,
      {
        "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
      }
    ],
    "string-quotes": "single",
    "order/properties-alphabetical-order": true
  },
  "ignoreFiles": ["**/node_modules/**"]
}
  • plugin: 使用したいstylelint-orderのような外部パッケージを記述する場所
  • extends: 使用したいルールのパッケージを記述する場所
  • rules: lintのルールを記述する場所
    • at-rule-no-unknown: 使用を許可する「標準的ではない@-規則」を記述する場所
    • string-quotes: 統一したいクォーテーションの種類を記述する場所
    • order/properties-alphabetical-order: CSSプロパティをアルファベット順に並べる
  • ignoreFiles: lintチェックの対象外とするファイルを記述する場所

Stylelintのチェックコマンド・修正コマンドを追加する

StyleLintESLinnt同様、コマンドを打たないとチェックや修正はしてくれないので、
あらかじめ、package.jsonにそのコマンドを登録しておきましょう。

commit時に自動でチェック・修正してくれる設定は後述。 その際にここで定義したコマンドを呼ぶようにするので、 ここで登録しておくのがいいかも。

以下のコマンドを追加しておきましょう。
これでnpm run lint:styleでチェックし
npm run lint:style:fixで整形することができるようになります。

pakage.json
  "scripts": {
    ...,
    "lint:style": "stylelint '**/*.{css,scss,sass}'",
    "lint:style:fix": "stylelint --fix '**/*.{css,scss,sass}'"
  }

(おまけ)VScodeの拡張機能を追加する

Stylelintという拡張機能を追加します。
これでリアルタイムにStyelintに違反している箇所を炙り出すことができます。

image.png

これでStylelintの導入は完了です!
お疲れ様です!

git commit時に自動でESLintStyleLintをチェックする

これまで、ESLintStyleLintを導入してコマンドを実行すれば、
チェックや整形ができるようにしてきました。

ここでは、git commitした時に自動でLintの整形・チェックを行なってくれるようにします。
その手順は以下の通りです。

  1. lint-stagehuskyをインストールする。
  2. git commit時に実行したいコマンドを登録する。
  3. huskyに2で登録したコマンドを呼び出すように設定

lint-stagehuskyをインストールする

ここでは、git commitされた時を検知し、指定したコマンドを実行してくれる
便利なパッケージ達であるhuskylint-stageをインストールしておきます。

パッケージ名 説明
lint-stage stageされたファイルだけをチェックする
husky commitを検知して特定のコマンドを実行させる

インストールコマンドは以下の通りです。

npm install -D husky lint-stage

git commit時に実行したいコマンドを登録する

git commitしたら
1. ESLint/StyleLintでコードを整形する
2. 整形した上で、各Lintに引っかかる構文がないか?をチェック

の2つが実行されるようにして行きたいと思います。
そのために、package.jsonに以下のコマンドを追加しましょう。

package.json
  "scripts": {
    ...,
    "lint": "eslint src --ext .js,jsx,.ts,.tsx",
    "lint:fix": "eslint src --ext .js,jsx,.ts,.tsx --fix",
    "lint:style": "stylelint '**/*.{css,scss,sass}'",
    "lint:style:fix": "stylelint --fix '**/*.{css,scss,sass}'",
    // 以下を追加
    "lint-staged": "lint-staged",
  }
  // 以下を追加
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": [ //(js,ts系のファイルに対して実行するコマンド)
      "npm run lint:fix",
      "npm run lint"
    ],
    "*.{css,scss}": [ //(スタイル系のファイルに対して実行するコマンド)
      "npm run lint:style:fix",
      "npm run lint:style"
    ]
  },

huskyに上の節で登録したコマンドを呼び出すように設定

続いて、git commitがコールされた時に実行して欲しいコマンドを登録しておきましょう。
まずは以下のコマンドを実行して下さい。

npx husky-init && npm install

すると.husky/pre-commitというファイルができているはずです。
このファイルに先ほど作ったlint-stageというコマンドを実行するように記述しましょう。

husky/pre-commit.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run lint-staged // ここを追記

これで、git commitを入力後すぐにリントの修正・チェックが走るようになりました。
お疲れ様です!

commitlintを導入する

commitlintはコミットメッセージをチェックしてくれる方です。

自分の過去のコミットをみると、コメントが適当すぎでコードを見ないと
何しているか不明なことが多々ある私には必要なパッケージです。

もう少しcommitlintについて知りたい人へ

commitlintについてもう少し詳しく

commitlintが許可するメッセージ例

commitlintを導入すると、git commit -m ...の度に、
「コミットメッセージ」がちゃんとテンプレに沿って書かれているかな??
と見てくれます。

commitlintはデフォルトで以下のようなコミットメッセージだけを通します。

title(scope): subject
// 空行
body
// 空行(省略可)
footer(省略可)

title, scope, subject, body, footer とは何か?

param 説明 備考
title 新機能か?バグ修正か?という情報 決められた値しか受け付けない(後述)
scope 影響範囲 影響を受けたファイルやディレクトリなど
subject 何をしたのか?を一行でまとめた情報。要約的な。
body なぜ、どのように、という詳しい情報を記述する。 数行で書いてOK
footer チケット番号とか。備考を書くみたい。 なくてもOK

とりわけtitleは以下の値しか受け付けないので、注意しましょう。

param 説明
build ビルド関係
ci CI関係
chore 雑事、タイポ修正とか軽微なものなど。
docs ドキュメント更新/追加/修正
feat 新機能の追加
fix バグフィックス
perf パフォーマンス
refactor リファクタリング
revert コミット取り消し(git revert)
style コードスタイル
test テスト

その他のルール

その他の詳細なルールなどはREADMEを見てもらうのが良さそうです。
自分でルールをカスタムできるみたいなので、お好きにどうぞ。

https://github.com/conventional-changelog/commitlint/#what-is-commitlint

commitlintに関する雑な感想

結構几帳面に見てくれます。一人で開発していると、ついつい「えいや!」で
適当なメッセージを残してしまうことがあるのでその抑止力になっていい気がします。

また、デフォルトのルールはAnglarチームの規約に則っているようなので、
特にこだわりがなければデフォルトのまま使っちゃっていいのかなと思います。

https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits


commitlint導入のステップは以下の通りです。

  1. commitlintに必要なパッケージをインストール
  2. commitlintの基本設定を記述
  3. commitlintを実行するコマンドを登録する
  4. commitlintcommitメッセージ入力後に実行させるように設定

commitlintに必要なパッケージをインストール

以下のコマンドでcommitlintをインストールします。

npm install -D @commitlint/{cli,config-conventional}

git commit時に自動でESLintStyleLintをチェックする」を読み飛ばした方へ

commitlint単体では、commitされた時に発動する!」という能力が使えないので
二人の助っ人も導入しましょう。lint-stageさんとhuskyさんです。

パッケージ名 説明
lint-stage stageされたファイルだけをチェックする
husky commitを検知して特定のコマンドを実行させる

以下のコマンドでインストールできます

npm install -D husky lint-stage

commitlintの基本設定を記述

commitlintの設定をpackage.jsonに記述します。

package.json
{
  ...,
  "commitlint": {
    "extends": [
      "@commitlint/config-conventional"
    ]
  }
}

なお、package.jsonに書きたくない!という人は
.commitlintrc.jsonというファイルを別途作成し、そこに記述してもOKです。

commitlintを実行するコマンドを登録する

commitlintを実行するコマンドをpackage.jsonに定義しておきましょう。

package.json
"scripts": {
    ...,
    // 追記
    "commitmsg": "commitlint -e $GIT_PARAMS"
  },

commitlintcommitメッセージ入力後に実行させるように設定

ここまでcommitlintのインストールと設定を行なってきました。
しかし、現状git commitを実行してもcommitlintは発動しません。

git commitでメッセージを入力し終えた時に、
commitlintが実行されるように設定して行きましょう。

git commit時に自動でESLintStyleLintをチェックする」を読み飛ばした方へ

git commit時に自動でESLintStyleLintをチェックする」の章で
記載したコマンドを実行していないとこの先のコマンドを実行しても
上手く動作しないと思うので以下のコマンドを実行してから先に進んでください

npx husky-init && npm install

そのためには先ほどインストールしたhuskyを使います。
まずは以下のコマンドを実行してみましょう。

npx husky add .husky/commit-msg

.husky/commit-msgというファイルができているはずです。
このファイルは「commitメッセージを記入後に実行されるコマンドを書くファイル」です。

このファイルにpackage.jsonに登録したコマンドを`記載するだけ
commitメッセージ入力後にcommitlintが実行されるようになります。

/husky/commit-msg.
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npm run commitmsg // ここを追記

これで、commitメッセージ入力後にチェックしてくれるようになりました。
お疲れ様です!

(番外編)VScodeの自動保存で整形するようにする。

ESLintStyleLintPrettierをVScodeで上手に活用するための
VScodeの設定をここに記述します。
VScodeを利用している人はsetting.jsonに以下を記述しておくといいでしょう。

setting.json
{
  // デフォルトのフォーマッタを prettier に設定
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  // ファイル保存時、prettier による自動フォーマット
  "editor.formatOnSave": true,
  // ファイル保存時、ESLint による自動フォーマット
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  },
  // css, scss ファイルは Stylelint でフォーマットするため、Pretteir によるフォーマットを回避
  "[css]": {
    "editor.formatOnSave": false
  },
  "[scss]": {
    "editor.formatOnSave": false
  },
  // VS Code  CSS, SCSS  Lint オフ
  // Stylelint とのバッティング回避
  "css.validate": false,
  "scss.validate": false
}

sassの導入

パッケージをインストールするだけです。楽ちん。

npm install -D sass

dependabotの導入

dependabotはプロジェクトで利用している依存ライブラリで
新しいバージョンが出たら自動でPRを作ってくれるという優れもの。

長い間npm auditしてなかったけど、気づいたら脆弱性がたっぷり
ということにならないためにも、自動で管理してくれるdependabotを導入しておくのは
いい選択肢なのではないでしょうか。

また、作成されたPRを条件付きの自動マージすることもできるので、
その設定方法についても記して行きます。

導入もシンプルなので、早速やって行きましょう。

dependabotの導入手順

dependabotに関してはパッケージを入れるではなく、
GitHubで設定するという方法で導入することになります。

導入は至って簡単。何よりもこのGif動画が一番分かりやすい。

一応画像でも示しておく。
1. GitHubへ飛んで、画面上部にあるinisightsのタブへ。
image.png

  1. Dependency graphを選択し、Dependabotをクリックする。
    image.png

  2. Enable Dependabotをクリック→Create config fileをクリック→適当にコミットメッセージを入れてCommit new fileをクリック。
    image.png

(おまけ)dependabotで作成されたPRを自動マージしよう

.github/workflows/のディレクトリ配下に以下のファイルを作成することで、
GitHub Actions で自動でdependabotにより作られたPRをマージしてくれます。

今回はパッチバージョンの更新だけ自動マージするように設定しましょう。

パッチバージョンとは
ver. 1.12.09 ← バージョン番号の右端。

dependabot-auto-merge.yml
name: Dependabot auto-merge
on: pull_request # PRが上がったら実行するで

permissions:
  pull-requests: write
  contents: write

jobs:
  dependabot:
    runs-on: ubuntu-latest  # ubuntuで実行するよ
    if: ${{ github.actor == 'dependabot[bot]' }} # PRあげたのがdependabotの時じゃないと実行しない
    steps:
      - name: Dependabot metadata
        id: metadata # このstepを`metadata`って名前で参照できるようにしとこ
        uses: dependabot/fetch-metadata@v1.1.1 # Dependabotが作成したPRから依存関係の情報を取得!
        with:
          github-token: '${{ secrets.GITHUB_TOKEN }}'
      - name: Enable auto-merge for Dependabot PRs
        if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' }} # パッチversionの更新じゃないなら処理しない。
        run: gh pr merge --auto --merge "$PR_URL" # mergeするよ
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

参考
- dependabot/fetch-metadata@v1.1.1とは
- GitHub Actionsのワークフロー構文

MaterialUIの導入

新しくアプリを作成する度、モーダルやボタンを一から自分で実装するのは
面倒なのですでに作成されているコンポーネントを使いまわせたらいいのになぁ

そんな欲望の末に生み出されたモンスターがMaterialUIです。(違う)

基本的なコンポーネントの集まりで、必要に応じて自分でスタイルを変更できるので、
「あ、こいつ 既存のコンポーネント使いまわしてるのバレバレw」ともなりません。

似たようなものにChakuraUIというものもあるみたいで、
こちらはコンポーネント数は少ないけどよりカスタム性に特化したライブラリのようです。

こちらも興味あるのですが、今回は私が使い慣れているMateriaUIを入れていこうと思います。

MaterialUIのインストール

以下のコマンドでインストールしましょう。

npm install @mui/material @emotion/react @emotion/styled @mui/icons-material

MaterialUIのスタイルを上書きした時に、上書いたCSSを優先する

自分で新たに追加したCSSよりもMaterialUIの持つスタイル情報が優先されて、
思ったように表示されないなんてことがあります。
そのようなことを防ぐために、上書きしたCSSを優先してね!という設定を行う必要があります。

やり方は簡単です。
pagesディレクトリの下にある_app.tsxを以下のように書き換えましょう。

_app.tsx
import '@/styles/globals.css';
import React from 'react';
import type { AppProps } from 'next/app';
import { StyledEngineProvider } from '@mui/material/styles'; // 追加

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <StyledEngineProvider injectFirst> // 追加
      <Component {...pageProps} />
    </StyledEngineProvider> // 追加
  );
}

export default MyApp;

<Component {...pageProps} />
<StyledEngineProvider>というタグで囲っているだけですね。

これをするだけで、全てのコンポーネントで
カスタムCSSを優先するというルールが適用されることになります。

(おまけ)themeの設定

MaterialUIにあるコンポーネントはデフォルトで
色や文字サイズが適当な値に設定されています。
例えば、デフォルトでButtonコンポーネントはこんな色です。

image.png

前述した通り、スタイルは自分で上書きできるのですが、
全てのコンポーネントで使用しているデフォルトの色を変更してあげれば、
わざわざ上書き用のCSSを書く必要が無くなるので嬉しい訳です。

そのような時に使えるのがthemeという訳です。
themeはデフォルトの値が詰まっている箱みたいなもので、
この箱の値を変更してあげることで、全てのコンポーネントでそれが適用されます。

それでは実際にデフォルト値を変更してみます。
まずは好きな場所にtheme.tsというファイルを作りましょう
私はstylesディレクトリ直下に作ることにします。

theme.ts
import { createTheme } from '@mui/material/styles';

// Create a theme instance.
const theme = createTheme({
  palette: {
    primary: { // ベースカラーを真っ黒にしちゃおう。
      main: '#000000'
    }
  }
});

export default theme;

次にこの定義したtheme全てのコンポーネントで適用されるようにしておきましょう。
_app.tsxに以下を追加して下さい。

_app.tsx
import '@/styles/globals.css';
import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles';  // ThemeProvider を追加
import type { AppProps } from 'next/app';
import React from 'react';
import theme from '@/styles/theme'; // 追加

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <StyledEngineProvider injectFirst>
      <ThemeProvider theme={theme}> //追加
        <Component {...pageProps} />
      </ThemeProvider> // 追加
    </StyledEngineProvider>
  );
}

これだけです。
すると先ほどのボタンは真っ黒になっていると思います。

image.png

他にもテキストの大きさなども変えることができるので、必要ろあらばいじってみて下さい。

Jestの導入

言わずと知れたテストライブラリです。
私の個人開発だとテストは後回しになりがちですが、
いつか書きたいとい気持ちも込めて入れておきます。
結局やらないのであれば消すだけでOKなので...。

ここで紹介する導入ステップは以下の通りです。

  1. Jestのインストール
  2. Jestの設定
  3. 仮テストの作成

Jestのインストール

以下のコマンドを実行しましょう

npm install -D jest @testing-library/react @types/jest @testing-library/jest-dom @testing-library/dom babel-jest @testing-library/user-event jest-css-modules

色々インストールしていますが、ざっくり言うと
Jestで必要になるパッケージ諸々」+「テストでCSSファイルが悪さしないようにモック化するパッケージ」
をインストールしています。

Jestの設定

.babelrcを作成する

.babelrcという名前でファイルを作成し、以下を記入して下さい。
これは、Jestに対して、「Next.jsのプロジェクトにテストするよ」と伝えるために必要みたいです。

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

package.jsonに設定を追加する

package.jsonに以下の設定を追加しておきましょう。
コメントの部分は削除して下さい。

package.json
    "jest": {
        "testPathIgnorePatterns": [ // テストの対象外となるディレクトリを記載
            "<rootDir>/.next/",
            "<rootDir>/node_modules/"
        ],
        "moduleNameMapper": {
            "\\.(scss)|(css)$": "<rootDir>/node_modules/jest-css-modules", // styleファイルに関しては`jest-css-modles`を使ってモックしますよ!
            "^@/(.*)$": "<rootDir>/src/$1" // import文が@で始まっていたら、それはsrcを示しているんだよ!
        }
    }

package.jsonにテスト実行用のコマンドを追加

package.jsonscriptに以下のコマンドを追加しておきましょう。

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

オプションは「テストファイルに対してテストが通ったかどうか?」ではなく、
「テストファイル内の全てのテストケースの結果を表示する」ために必要なものになります。

仮テストの作成

設定がうまくいっているかを確認するために、仮の簡単なテストを書いておきましょう。

まずは___tests___というディレクトリをルートに作成しましょう。
その中に仮のテストファイルHome.test.tsxというファイルを作成し、以下をコピペして下さい。

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

it('Should render hello text ', () => {
  render(<Home />);
  expect(screen.getByText('Next.js Template')).toBeInTheDocument();
});

Jestの話もしだすと長くなってしまうので、ざっくり説明すると、
<Home>コンポーネントの中にNext.js Templateという文字列が
あるかどうかを確認するよ!というテストコードになります。

新しく作ったNext.jsのプロジェクトにはindex.tsxという名前のファイルが
あると思いますが、その中にHomeコンポーネントが定義されているはずです。

その中にNext.js Templateという文字列を含めておきましょう。
私は以下みたいな感じにしておきます。

index.tsx
      ...
      <main className={styles.main}>
        <h1 className={styles.title}>
          Next.js Template /* ←ここに追加しました */
        </h1>

        <p className={styles.description}>
          Get started by editing <code className={styles.code}>pages/index.tsx</code>
        </p>
      ...

これでnpm run testを実行してみて下さい。テスト通るはずです。
逆にNext.js Templateの文字を削除してテストすると
エラーが表示されると思います。

これでJestの導入は完了です!
お疲れ様でした!

StoryBookの導入

StoryBook。それは、デザイナーとの意思疎通を容易にするべく
作成したコンポーネントのデザインを確認できるカタログを自動で生成してくれる人。

「個人開発で一人でやっているから、オイラは関係ないや。グヘヘェ」
と私は思いました。

ですがこいつは見た目のテストをするためにも役立つ優れものだとか。
規模が大きくなり、1つのコンポーネントを複数の場所で使っていると
いつの間にかスタイルおかしくなっている!なんてことがあります。

それを防ぐことができるというのは嬉しいもの。
導入の手順は以下の通りです。

  1. StoryBookのインストール
  2. StoryBookの設定変更
  3. カタログを作ってみる
  4. Chromaticのインストール
  5. GitHub Actions の設定

StoryBook のインストール

とっても簡単です。以下のコマンドを実行するだけ!

npx sb init --builder webpack5

こちらを実行すると以下が行われます。

  • パッケージのインストール
  • コマンドのエイリアスをpackage.jsonに登録
  • .storybookディレクトリと設定ファイルの作成
  • storiesディレクトリとサンプルファイルの作成

StoryBookの設定変更

設定を少しだけいじります。
.storybookというディレクトリの中に.main.jsというファイルがあるはずです。
こちらに以下を追記してあげてください。

main.js
const path = require('path'); // 追加

module.exports = {
  stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
  core: {
    builder: 'webpack5',
  },
  // ここから
  webpackFinal: async (config) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../src'),
    };
    return config;
  }
  // ここまで追加
};

これは、import文が@/...というように@から始まっている場合でも
パスを認識できるようにするための設定です。

カタログを作ってみる

カタログを作ってみましょう。
既存のindex.tsxで定義されているHomeコンポーネントをカタログに登録してみましょう。

まずはstoriesディレクトリの中にhome.stories.tsxというファイルを作成し、
以下をコピペしてあげてください。

home.stories.tsx
import Home from '@/pages/index';

const home = {
  title: 'Pages/Home',
  component: Home,
};

export const HomePage = () => <Home />;

export default home;

続いてカタログをローカルサーバーで表示させるために以下のコマンドを実行します。

npm run storybook

そしてlocalhost:6006を見てみると、
画像のようにHomeコンポーネントがカタログに表示されいるのが確認できるでしょう。

image.png

デフォルトでは、サンプルのファイルが存在しているので、画像とは違ってHomeコンポーネント以外も表示されていると思います。この画像ではそれを消した状態のものです。

ここまででひとまずStoryBookのカタログ機能に入門することができました。
やったね☆

Chromaticのインストール

この説ではChromaticと呼ばれるものをインストールします。
これはStoryBookと連携して、コンポーネントの見た目の変化を検知し、
比較検証を簡単にできるようにするツールです。

まずはChromatic公式へ飛んでGet Started nowをクリック!
そのまま案内に従ってポチポチしていくと以下のような画面に行くと思うので、
自分のリポジトリを選択してさらに進みます。

image.png

少し進むと画面に表示されている2つのコマンドを実行してくれよな!
と言われると思います。以下の2つのコマンドです。

npm install --save-dev chromatic
npx chromatic --project-token=プロジェクトごとの固有の値

素直に実行してみましょう。しばらく待つと画面遷移し、以下のような画面になると思います。

image.png

すると今度は、「スタイルの違い検知してみせるから何かstyleいじってみろよ!」
と言われます。いじってやりましょう。なんでもいいのですが、
Home.module.cssをいじってみることにします。

Home.module.css
.main {
  align-items: center;
  display: flex;
  flex: 1;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  padding: 8rem 0; /* 変化させてみる 4rem -> 8rem */
}

そして再度、以下のコマンドを実行します。

npx chromatic --project-token=プロジェクトごとの固有の値

すると、Chromaticが変更を検知してみやすく表示してくれます。
以下のような感じです。素敵です。

image.png

GitHub Actions の設定

これまでStoryBook&Chromaticのカッコ良いところを見てきました。
でも私の理想的なフローは以下なので、もう少し設定を頑張ります。

  1. GitHubでPR出した時に自動でチェック
  2. 意図していない時に変更が検知されたら、それをチェックする。
  3. 問題なければapproveしてmerge !

そのためにはGitHub Actionsでワークフローを作成する必要があります。
以下を.github/workflows/の直下に作成しましょう!

chromatic-ui-test.yml
name: Chromatic

on:
  push: # pushされたら実行するよ
    branches:  # ブランチ名が以下じゃなければ実行しないよ
      - with_storybook # ここは適宜変更して下さい
jobs:
  build:
    runs-on: ubuntu-latest # ubuntu環境で実行します

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - run: npm ci
      - uses: chromaui/action@v1
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}

このファイルで定義されているCHROMATIC_PROJECT_TOKENという変数の値は、
GitHubに自分で定義する必要があります。
簡単にできるので、以下の手順で進めていきましょう!

まずはGitHubのSettingタブへ移動して下さい。

image.png

続いて、画面左側にあるSecretsをクリック!
さらにさらに、New repository secretをクリック。

image.png

NameCHROMATIC_PROJECT_TOKENと入力し、
valueに自分のトークンを入力してください。
これで準備は完了です!

先ほど作ったchromatic-ui-test.ymlで定義したブランチ名でpushすれば、
ChromaticUIのチェックが実行されていることが確認できるはずです。

image.png

お疲れ様です!これでUIテストを行う環境もできました!

最後に

長かったですね。お疲れ様です。

この記事の通りに実行して行ってもnodenpm,yarn
バージョンの違いやOSの違いなどでエラーが出てしまって「まぢムリ」
となってしまうこともあるかもしれません。

私はよくそういうことあります。
エラーが出て、先人の奮闘記からコードをコピペしたけど
やっぱり直らん。ということが。

いつになったら英語の公式ドキュメントに臆さない
キラキラスーパーエンジニアになれるのかは不明です。

今は個人開発などで色々奮闘しているので、
よかったら他の記事も見たりTwitterをフォローしてみましょう。

私のTwitter

18
18
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
18
18