Closed5

個人開発用のテンプレートを作る

tara is oktara is ok

nextアプリの初期設定

こちらを参考に実施していく
https://nextjs.org/docs/getting-started/installation

nodeのバージョンを確認

System Requirements:
Node.js 18.17 or later.

とあるので、一応確認

node -v
v20.10.0

next.jsのインストール

npx create-next-app@latest
Need to install the following packages:
create-next-app@14.0.4
Ok to proceed? (y) 
✔ What is your project named? … template-next
✔ Would you like to use TypeScript? … Yes
✔ Would you like to use ESLint? … Yes
✔ Would you like to use Tailwind CSS? … Yes
✔ Would you like to use `src/` directory? … Yes
✔ Would you like to use App Router? (recommended) … Yes
✔ Would you like to customize the default import alias (@/*)? … Yes
? What import alias would you like configured? › @/*

今回は最新のNextの勉強も兼ねているためrecommendされているものは全てYesで回答する。

また、? What import alias would you like configured? › @/*については、
ファイルパスの先頭に@/と指定するとプロジェクトディレクトリとなるようエイリアスの設定をしている

確認

template-next && code .
package.json
{
  "name": "template-next",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "react": "^18",
    "react-dom": "^18",
    "next": "14.0.4"
  },
  "devDependencies": {
    "typescript": "^5",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "autoprefixer": "^10.0.1",
    "postcss": "^8",
    "tailwindcss": "^3.3.0",
    "eslint": "^8",
    "eslint-config-next": "14.0.4"
  }
}

動作確認

npm run dev

以下が表示されることを確認

git管理

ここまでの設定内容をコミットしておく。
また、リポジトリはすでに作成済とする

git init
git remote add origin [your remote repository]
git branch -M main
git push -u origin main
tara is oktara is ok

Prettier

npm install -D prettier
.prettierrc.json
{
    "semi": false,
    "singleQuote": true,
    "trailingComma": "all"
}
tara is oktara is ok

ESLint

こちらを元に作成していく
https://zenn.dev/tara_is_ok/articles/271aebe29f921e

  1. .eslintrc.json.eslintrc.jsに変更
  2. 関連packageのinstall
npm install -D @typescript-eslint/eslint-plugin eslint-plugin-eslint-comments @typescript-eslint/parser eslint-config-prettier eslint-plugin-import eslint-plugin-react eslint-plugin-simple-import-sort

package.jsonは以下のようになります

package.json
{
  "name": "template-next",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
+    "prepare": "husky install"
  },
  "dependencies": {
    "next": "14.0.4",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
+    "@typescript-eslint/eslint-plugin": "^6.14.0",
+    "@typescript-eslint/parser": "^6.14.0",
    "autoprefixer": "^10.0.1",
    "eslint": "^8",
    "eslint-config-next": "14.0.4",
+    "eslint-config-prettier": "^9.1.0",
+    "eslint-plugin-eslint-comments": "^3.2.0",
+    "eslint-plugin-import": "^2.29.1",
+    "eslint-plugin-react": "^7.33.2",
+    "eslint-plugin-simple-import-sort": "^10.0.0",
+    "husky": "^8.0.0",
+    "lint-staged": "^15.2.0",
    "postcss": "^8",
    "prettier": "^3.1.1",
    "tailwindcss": "^3.3.0",
    "typescript": "^5"
  }
}

  1. 先ほどの記事の.eslintrc.jsをコピーし貼り付け
    storybookや、不要なoverrideは削除する
.eslintrc.js
module.exports = {
  extends: [
    'next/core-web-vitals',
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:react/recommended',
    'plugin:react-hooks/recommended',
    'plugin:react/jsx-runtime',
    'plugin:eslint-comments/recommended',
    'prettier',
  ],
  env: { browser: true, node: true, es6: true },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 'latest',
    sourceType: 'module',
    project: './tsconfig.json',
    tsconfigRootDir: __dirname,
  },
  plugins: ['@typescript-eslint', 'simple-import-sort', 'import'],
  ignorePatterns: ['node_modules/', '.eslintrc.js'],
  rules: {
    'react/jsx-curly-brace-presence': 'warn',
    'simple-import-sort/imports': 'error', //importとexportのソート
    'simple-import-sort/exports': 'error',
    'import/first': 'error',
    'import/newline-after-import': 'error',
    'import/no-duplicates': 'error',
    '@typescript-eslint/consistent-type-definitions': ['warn', 'type'], //型定義はtypeを使う
    '@typescript-eslint/no-explicit-any': 'error', //any禁止
    '@typescript-eslint/no-unused-vars': 'error', //未使用の変数禁止
    'react/self-closing-comp': ['error', { component: true, html: true }], //<Component />のように自己閉タグを使う
    'no-control-regex': 'off', //正規表現中のASCII制御文字ok
    'react/jsx-boolean-value': 'error', //attribute={true} → attribute
    'react/jsx-pascal-case': 'error', //コンポーネント名はパスカルケース
    'object-shorthand': ['warn', 'properties', { avoidQuotes: true }],
    'eslint-comments/require-description': 'error', //eslint-disable-next-lineのコメントは必ず説明を書く。https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/require-description.html
    'eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], //https://mysticatea.github.io/eslint-plugin-eslint-comments/rules/disable-enable-pair.html
    'import/no-default-export': 'error', //default export禁止
    'no-nested-ternary': 'error', //三項演算子のネスト禁止
    'react/function-component-definition': [
      'error', //関数コンポーネントの定義はアロー関数を使う
      { namedComponents: 'arrow-function' },
    ],
    'no-magic-numbers': [
      'error',
      {
        ignore: [-1, 0, 1], //配列検索でindexOf === -1などは許容する
        ignoreDefaultValues: true, //const { tax = 0.1 } = props
        ignoreArrayIndexes: true, //data[100] ok
        enforceConst: true, //マジックナンバーはconstで定義する
      },
    ],
    '@typescript-eslint/naming-convention': [
      'error',
      {
        selector: ['variable', 'method', 'accessor'], //基本的に全てcamelCase
        format: ['camelCase', 'snake_case'],
      },
      {
        selector: ['property'], //APIリクエスト時にPascalCaseとなっている箇所がある
        format: ['camelCase', 'snake_case', 'PascalCase'],
      },
      {
        selector: 'variable', //exportされている定数やコンポーネント
        modifiers: ['exported', 'const'],
        format: ['PascalCase', 'strictCamelCase'],
      },
      {
        selector: 'interface', //interfaceはIをつけない
        format: ['PascalCase'],
        custom: { regex: '^I[A-Z]', match: false },
      },
      { selector: ['class', 'typeAlias', 'enum'], format: ['PascalCase'] },
      {
        selector: ['objectLiteralProperty'], //api requestのheadersの'Content-Type'などが対応するためnullで許容する
        format: null,
        modifiers: ['requiresQuotes'],
      },
    ],
  },
  overrides: [
    {
      files: ['page.tsx', 'layout.tsx', 'tailwind.config.ts'],
      rules: {
        'import/no-default-export': 'off',
        'import/prefer-default-export': 'error',
        '@typescript-eslint/naming-convention': 'off',
      },
    },
  ],
}

huskyとlint-stagedでコミット前にlintを走らせる

以下の手順通りに実行していく
https://typicode.github.io/husky/getting-started.html

  1. huskyのインストール
npx husky-init && npm install
  1. lint-stagedのインストール
npm install -D lint-staged
  1. .husky/pre-commitにコマンドを追加する
npx husky set .husky/pre-commit "npx lint-staged"

以下のようになっていればok

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

npx lint-staged
  1. ステージングに上がっているファイルのみを対象とする設定を追加

https://nextjs.org/docs/pages/building-your-application/configuring/eslint#linting-custom-directories-and-files

.lintstagedrc.js
const path = require('path')

const buildEslintCommand = (filenames) =>
  `next lint --file --fix ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' --file ')}`

module.exports = {
  '*.@{js,jsx,ts,tsx}': [buildEslintCommand, 'prettier --write'],
}

この記事を参考にさせていただきました🙇‍♂️
https://zenn.dev/risu729/articles/latest-husky-lint-staged

tara is oktara is ok

pre-commitが動かない

タイポしてた🥲🥲🥲🥲🥲🥲

.lintstagedrc.js
const path = require('path')

const buildEslintCommand = (filenames) =>
  `next lint --fix --file ${filenames
    .map((f) => path.relative(process.cwd(), f))
    .join(' --file ')}`

module.exports = {
- '*.@{js,jsx,ts,tsx}': [
+  '*.{js,jsx,ts,tsx}': [
    () => 'tsc --incremental false --noEmit',
    buildEslintCommand,
    'prettier --write',
  ],
}

tara is oktara is ok

app routerに対応したeslintを設定する

app routerでは/app配下のpage.tsxのみをroutingの対象とするようなので、default export の制限を/app配下の全てのpage.tsxに変更する

.eslintrc.js
{
~~~
  overrides: [
    {
-      files: ['page.tsx', 'layout.tsx', 'tailwind.config.ts'],
+      files: ['*/app/**/page.tsx', 'layout.tsx', 'tailwind.config.ts'],
      rules: {
        'import/no-default-export': 'off',
        'import/prefer-default-export': 'error',
        '@typescript-eslint/naming-convention': 'off',
      },
    },
  ],
}
このスクラップは2023/12/18にクローズされました