Next.js + Typescript環境構築
何か作ろうとしたり試したりするたびに毎度1から構築するのが面倒なので、
よく使うパターンでコードベースを作成しておく。
前提
- PC: M1 Mackbook Air
- OS: Mounterey 12.4
- Docker: v20.10.14
- VS Code + Remote Container
ローカルを汚したくないので先ずはNode用のDockerfile
を作成。
FROM node:16
作成したらVS CodeのRemote Containerで作成したDockerfile
を読み込む。
公式のコマンドでNext.js + Typescript環境を作成
npx create-next-app --typescript
よく使うライブラリを追加していく。
Jest
yarn add -D jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom
※ Jest 28~jext-environment-jsdom
を追加しないとjest実行時に怒られるので入れること
const nextJest = require("next/jest");
const createJestConfig = nextJest({
// next.config.jsとテスト環境用の.envファイルが配置されたディレクトリをセット。基本は"./"で良い。
dir: "./",
});
// Jestのカスタム設定を設置する場所。従来のプロパティはここで定義。
const customJestConfig = {
// jest.setup.jsを作成する場合のみ定義。
// setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
moduleNameMapper: {
// aliasを定義 (tsconfig.jsonのcompilerOptions>pathsの定義に合わせる)
"^@/(.*)$": "<rootDir>/src/$1",
},
testEnvironment: "jest-environment-jsdom",
};
// createJestConfigを定義することによって、本ファイルで定義された設定がNext.jsの設定に反映されます
module.exports = createJestConfig(customJestConfig);
configについては以下を参考にさせていただきました。
Storybook
- 初期導入
npx sb init
Need to install the following packages:
と聞かれたらy
でパッケージをインストールしてあげる。
Prettier
- インストール
create-next-app
でESLintは導入されてるため、Typescript用のESLintと組み合わせる前提として以下でインストール
yarn add -D prettier eslint-config-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin
- config
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
"next/core-web-vitals",
"eslint:recommended",
// TypeScriptでチェックされる項目をLintから除外する設定
"plugin:@typescript-eslint/recommended",
// prettierのextendsは他のextendsより後に記述する
"prettier",
],
plugins: ["@typescript-eslint"],
// ESLintでTypescriptを解析する
parser: "@typescript-eslint/parser",
parserOptions: {
sourceType: "module",
// TypeScriptのLint時に参照するconfigファイルを指定
project: "./tsconfig.json",
},
// 上位ディレクトリにある親のeslintrcを参照しないようにする
root: true,
rules: {},
};
{
"printWidth": 120,
"trailingComma": "all",
"tabWidth": 2,
"semi": false,
"singleQuote": true,
"jsxSingleQuote": true
}
- VS Codeのソース保存時の自動整形
settings.jsonに以下を追加
※とりあえず全ソースに適用してるけど、不便な場合は拡張子指定する
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
MSW
- Storybookでも使えるようにしておく
yarn add -D msw msw-storybook-addon
- 絶対パスインポートが効くようにwebpack設定
module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions'],
webpackFinal: async (config) => {
config.resolve.alias = { ...(config.resolve.alias || []), '@': path.resolve(__dirname, '../src') }
return config
},
framework: '@storybook/react',
core: {
builder: '@storybook/builder-webpack5',
},
}
あれ?node_modules
のimport
補完が効かない。。。
完全にツボにハマった(泣
一旦保留しよう。。。
とりあえず一旦リポジトリに突っ込んでまた今度(逃
お!今日起動しなおしたら効くようになった!これで勝つる!!
ESLint追加設定
- scripts, VS Code保存時にimportいい感じにしてくれるように以下を追加
yarn add -D eslint-plugin-unused-imports eslint-plugin-import
- config
とりあえずグループごとにソートされればOKとしておく。
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
'next/core-web-vitals',
'eslint:recommended',
// TypeScriptでチェックされる項目をLintから除外する設定
'plugin:@typescript-eslint/recommended',
// prettierのextendsは他のextendsより後に記述する
'prettier',
],
plugins: ['@typescript-eslint', 'import', 'unused-imports'],
// ESLintでTypescriptを解析する
parser: '@typescript-eslint/parser',
parserOptions: {
sourceType: 'module',
// TypeScriptのLint時に参照するconfigファイルを指定
project: './tsconfig.json',
},
// 上位ディレクトリにある親のeslintrcを参照しないようにする
root: true,
rules: {
'@typescript-eslint/no-unused-vars': 'off', // or "no-unused-vars"
'unused-imports/no-unused-imports': 'error',
'unused-imports/no-unused-vars': [
'warn',
{ vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
],
'import/order': [
'error',
{
// グループごとの並び順
groups: [
'builtin', // 1. fsや path などの node "builtin" のモジュール
'external', // 2. npm install したパッケージ
'internal', // 3. webpack などでパス設定したモジュール
['parent', 'sibling'], // 4. 親階層と小階層のファイル
'object', // object"-imports
'type', // 型だけをインポートする type imports
'index', // 同階層のファイル
],
},
],
},
}
pre-commit, pre-push
- commit, pushの前にLintやFormatなど実行しがちなので以下を追加
yarn add -D husky lint-staged
npx husky-init && yarn
# husky-init無いからインストールするで?と聞かれたらy
- husky
pre-commitはステージングされたts,tsx
だけを対象としてPrettier
, ESLint
の順にfix
で実行
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# ステージングされたts,tsxファイルをスペース区切りで取得
files=`git diff --cached --name-only | grep -E "*.ts|tsx$" | tr "\r\n" " " | tr "\n" " "`
if [ -n ${files} && ${#files(@)} > 0 ]; then
echo "[pre-commit] Find *.tx|tsx, Exec ESLint & Prettier fix."
yarn format:fix $files
ret=$?
if [ $ret != 0 ]; then
echo "[pre-commit] Prettier fix error."
exit $ret
fi
yarn eslint:fix $files
ret=$?
if [ $ret != 0 ]; then
echo "[pre-commit] ESLint fix error."
exit $ret
fi
fi
exit 0
pre-pushは全体に適用したいが、ファイル数が多くなると極端に遅くなるTypecheckを実行
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
# commitされたts,tsxファイルを取得
files=`git log HEAD^..HEAD --name-only --oneline | grep -E "*.ts|tsx$"`
if [ -n ${files} && ${#files(@)} > 0 ]; then
echo "[pre-push] Find *.tx|tsx, Exec Typechecking"
yarn tsc
ret=$?
if [ $ret != 0 ]; then
echo "[pre-commit] Typechecking error."
exit $ret
fi
fi
exit 0
だいぶ仕上がってきた気がするので一旦ここまで。