Next.jsをTypeScriptで使用するときのテンプレートを作りました。
nextjs-with-typescript-template
Reactを使った素振りでなにか作るときにNext.jsで始めるということが今後増えていきそうという理由で作った、よく使いそうなツールをまとめた自分用のテンプレートです。
型チェック
tscで型チェックを行います。
設定のベースは、create-next-app
のwith-typescript
テンプレートです。一部理解できていないオプションもあります。
// tsconfig.json
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "es2017"],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"strict": true,
"target": "esnext"
},
"exclude": ["node_modules"],
"include": ["**/*.ts", "**/*.tsx"]
}
上記のオプションについて
allowJs
ts, tsxファイル以外のimportの許容。
alwaysStrict
各ファイルへ"use strict"をつけて出力することを保証する。出力されたJSファイルはECMAScriptのStrictモードで実行される。
Strictモードについては以下を参照。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode
forceConsistentCasingInFileNames
ファイル名の大文字小文字を区別する。
jsx
jsx構文がどのようにファイルに出力されるかを制御するオプション。preserve, react, react-nativeがありpreserveではJSXを変更することなく.jsxファイルを出力する。
lib
コンパイルする際に使用する組み込みのJS API型定義や、ブラウザ上で使用されるAPIの型定義のライブラリを指定する。
module
出力されるJSのモジュールの形式を指定する。CommonJS形式(exports.*)かESModules(export ***)かを指定。
noEmit
JavaScript ソースコード、ソースマップ、型定義のファイルを出力しないようにします。型チェック機能だけを使用する場合にtrueにする。Next.jsはtscを使わずに内部でBabelでコンパイルしているらしい。
noFallthroughCasesInSwitch
switch 文において、次の case へ処理を持ち越した場合にエラーを報告する。 switch 文内の空でない case 句が、break
またはreturn
を含むことを確約する。
noUnusedLocals
利用されていないローカル変数について、エラーを報告する。
noUnusedParameters
利用されていない関数のパラメータについて、エラーを報告する。
resolveJsonModule
.json拡張子のファイルをモジュールとしてimportできるようにする。
skipLibCheck
型定義ファイルのチェックをスキップすることで、コンパイル実行時間を短縮する。
strict
プログラムの正しさを強く保証するための幅広い型チェックの挙動を有効化する。strictBindCallApply, strictFunctionTypes, strictNullChecks, strictPropertyInitialization
オプションの有効化と等価。
target
出力されるJSのバージョンの指定。
理解できていないオプション
- isolatedModules
- moduleResolution
- esModuleInterop
linter, formatter
ESLint + Prettierの構成です。
// .eslintrc.json
{
"parser": "@typescript-eslint/parser",
"extends": [
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:prettier/recommended",
"plugin:prettier/react",
"plugin:prettier/@typescript-eslint"
],
"plugins": ["@typescript-eslint", "react", "prettier"],
"rules": {
"react/react-in-jsx-scope": "off"
},
"globals": {
"React": "writable"
}
}
上記の設定について
parser
ESLintがTypeScriptをパースできるようにするためのパーサの指定。
extends
pluginによって提供されるルールを使用することによって設定を拡張するという理解。「plugin:{プラグイン名}/{設定名}」という形で指定する。
- plugin:@typescript-eslint/recommended
TypeScript用のESLintルール
- plugin:react/recommended
React用のESLintルール
- plugin:prettier/recommended
ESLintとPrettierを共存させるためのルール。ESLintのフォーマットに関する設定を全てOFFにし、フォーマットに関してはESLintの中からPrettierにすべて任せる
- plugin:prettier/react
eslint-plugin-reactのフォーマットに関するルールをOFFにする。
- plugin:prettier/@typescript-eslint
競合するESLintのルールを無効化する。最後に書く必要があるっぽい。
plugins
eslint-plugin-xxxのxxxの部分を指定する(eslint-plugin-は省略可能なため)。xxxに関する設定の塊みたいな認識。
- @typescript-eslint
- react
- prettier
rules
特定のルール(最小単位)のON/OFFを切り替える。
- react/react-in-jsx-scope
Next.jsでは各jsx/tsxファイル内でReactをimportする必要がないので、OFFにする。
globals
実行時に追加するグローバル変数の追加の指定。writableを指定することで変数に対しての書き込みも可能になる。
- React
Next.jsでは各jsx/tsxファイルでReactをimportしないため。
フォーマットに関する設定は.prettierrcに書く。
// .prettierrc
{
"semi": true,
"singleQuote": true
}
テスト
jestでユニットテストを実行します。
// jest.config.js
module.exports = {
roots: ['<rootDir>/src'],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/?(*.)+(spec|test).+(ts|tsx|js)',
],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
};
今回作ったテンプレートでは「tests」というディレクトリを作って、その中に「xxx.test.ts」のようなファイルを作ってyarn test
でテストを実行するようにしています。
precommit
huskyを使用して、precommitのhookで型チェック・lint・テストを回しています。
規約を破るソースコードはpushさせないという思想です。
テンプレートを作ってみた感想
- 設定が多い。とはいえ、Next.jsがBabelやwebpackの設定を隠蔽してくれているので楽な方なんだと思う。
- ESLintは特に複雑に感じる。ただ、今回テンプレートを作ってみたことでESLintへの理解度は上がった。
- 大変だけど、最初にこのへんの設定をセットアップしておけば後から設定の中身を変更することは大変じゃないのでテンプレートを作った価値はあった。特にリントツールは初期に導入を済ませておくことに価値があるはず。
- このテンプレートを使ってNext.jsの素振り頑張る。