Next.jsのプロジェクトを始める時にやっていること

投稿日
Next.jsのプロジェクトを始める時にやっていること

Next.jsのプロジェクトを始める際にテンプレート的に行っていることを記載します。

ざっくり以下の手順で進めます。

  1. 前準備
  2. Next.jsの初期化
  3. Prettierの設定
  4. ESLintの設定

検証した環境

1 Next.js 14.1.3
2 pnpm 8.15.3
3 volta 1.1.1
4 prettier 3.2.5

前準備

GitHubの準備

GitHubでプロジェクトを前もって作成します。

ここではnextjs-baseという名前で作成しました。

GitHubにプロジェクトを作成


私はghqを使ってリポジトリ管理をしているのでghqを使ってcloneします

ghq get git@github.com:yuki-takara/nextjs-base.git


作成したリポジトリのフォルダでgit関連の初期化を行います

# 作成したリポジトリのフォルダに移動
cd {作成したリポジトリのフォルダ}
 
# GitHub上に表示されている初期化のコマンドをそのままコピペ
echo "# nextjs-base" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:yuki-takara/nextjs-base.git
git push -u origin main

first commitがコミット出来て、GitHub上に連携出来ていればOK!

$ git log --oneline
26eea93 (HEAD -> main, origin/main) first commit

GitHubへの連携も完了

nodeの設定

せっかくなのでnodeのバージョン管理としてvoltaを利用してみます!



voltaを使う上でpackage.jsonを用意します

pnpm init

pakage.jsonが作られるので最低限のものを残しつつ編集します

package.json
{
  "name": "nextjs-base",
  "version": "0.0.1",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "license": "ISC"
}


voltaの記述を追記、記述時点のLTSを記載しました

package.json
{
  "name": "nextjs-base",
  "version": "0.0.1",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "license": "ISC",
  "volta": {
    "node": "20.11.1"
  }
}
$ node -v
v20.11.1

package.jsonに記載したvoltaでのバージョンが使えるようになりました!

Next.jsの初期化

公式ページに従って作成します

https://nextjs.org/docs/getting-started/installation


pnpm dlx create-next-app@latest

聞かれる質問は全てデフォルトのまま進めました

✔ What is your project named? … my-app
✔ 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 (@/*)? … No
Next.jsの初期化を行う


階層を深くする理由が特にないので、

my-appとして作成した中身を隠しファイルも含めて移動します

初期化コマンドで作成したフォルダの中身をルートフォルダに移動

package.jsonも上書きされるのでnameやvoltaの記述を更新します

package.json
{
  "name": "nextjs-base",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "react": "^18",
    "react-dom": "^18",
    "next": "14.1.3"
  },
  "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.1.3"
  },
  "volta": {
    "node": "20.11.1"
  }
}

dev環境が起動することを確認していきます

$ pnpm run dev
 
> nextjs-base@0.0.1 dev /Users/yuu/src/github.com/yuki-takara/nextjs-base
> next dev
 
    Next.js 14.1.3
   - Local:        http://localhost:3000

http://localhost:3000 にアクセスして開発環境が動作しました!

開発環境の起動を確認

Prettierの設定

FormatterにPrettierを導入します


Biome も話題に上がってますが、まだPrettierが一般的なイメージが強いためここではPrettierにしました。

pnpm add -D prettier


Prettierの設定ファイルは .prettierrc .prettierrc.js 等、様々な形式で用意が可能です。

ここでは prettier.config.js として作成していきます

prettier.config.js
module.exports = {
  endOfLine: "lf",
  semi: false,
  singleQuote: true,
  printWidth: 100,
  arrowParens: 'avoid',
}

Prettierの設定は好みが出るところで私は↑のような設定することが多いです。


「コメントが出来る」 という点で .js.yml のファイル種類を選ぶのが理想形なイメージがあり私は .prettierrc.js とする事が多かったのですが、

海外の方のリポジトリを見る限り prettier.config.js とされている事が多いように感じました 📝



Googleのコーディングガイドを参考にすると以下のようになるそうです

(ChatGPT先生にお願いしたら作ってくれました。ありがた過ぎる。。)
prettier.config.js
module.exports = {
  // Googleスタイルガイドに従い、インデントには2つのスペースを使用
  tabWidth: 2,
  // セミコロンを省略せずに使用
  semi: true,
  // シングルクォートを使用
  singleQuote: true,
  // オブジェクトのプロパティのキーが必要な場合のみクォートを使用
  quoteProps: 'as-needed',
  // 配列やオブジェクトの要素の最後にもカンマを付ける(ES5で有効な場合のみ)
  trailingComma: 'es5',
  // 複数行の場合、配列の括弧内に改行を入れる
  bracketSpacing: true,
  // アロー関数のパラメータが1つのみの場合も括弧を付ける
  arrowParens: 'always',
  // HTMLやJSXの閉じタグを改行しない
  jsxBracketSameLine: false,
  // HTMLやJSXの属性にシングルクォートを使用
  jsxSingleQuote: true,
  // ファイルの末尾に改行を入れる
  endOfLine: 'lf',
};


最後にPrettierを全体的に実行して完了です!

pnpmのlockファイルがYAMLなので拡張子を指定してみました
pnpm dlx prettier --write "**/*.{ts,tsx,json,mjs,css}"
Prettierをプロジェクト全体に実行

ESLintの設定

FormatterのPrettierでカバー出来ない部分はESLintで補ってもらいます



ここでは以前書いた記事の中から2つを取り入れることにしました

  • eslint-config-prettier
  • eslint-plugin-unicorn

少し前は airbnb を入れるのが主流だったイメージが強いのですが、

最近はそんな事もなくなってきている感覚があったため↑に記載した2つにしました

.eslintrc.json → .eslintrc.js

Prettierと同じく.jsonだとコメントが出来ないため、

ESLintの設定ファイルの拡張子を前もって .js に変更します

.eslintrc.json
{
  "extends": "next/core-web-vitals"
}
.eslintrc.js
module.exports = {
  extends: 'next/core-web-vitals',
}

eslint-config-prettier

PrettierとESLintの設定がバッティングしないようにします

pnpm add -D eslint-config-prettier
.eslintrc.js
module.exports = {
  extends: ['next/core-web-vitals', 'prettier'],
}

設定を更新してLintで怒られないことを確認します

$ pnpm run lint
> next lint
 
 No ESLint warnings or errors

eslint-plugin-unicorn

公式ページ

More than 100 powerful ESLint rules

と書かれているように、ESLintをより強力にするルール集です!

More than 100 powerful ESLint rules
4.3k
365
JavaScript

1度使ってみたらハマってしまってほぼ全てのプロジェクトに導入しています 😂



pnpm add -D eslint-plugin-unicorn
.eslintrc.js
module.exports = {
  extends: ['next/core-web-vitals', 'plugin:unicorn/recommended', 'prettier'],
}

設定を更新してLintで怒られ、、ない?

$ pnpm run lint
> next lint
 
 No ESLint warnings or errors

以前だとこの段階で怒られていた記憶があるものの

これだとちゃんと適用出来ているか分からないのでちゃんと効いているか確認していきます


eslint-plugin-unicorn は厳しいルールも多いため、

適宜ルールの変更・停止等行ってプロジェクトに合わせていく必要が出てきます。


プロジェクト途中で導入するとLintの対応だけでかなりの時間を使うケースも往々にして起こり得ます

ESLint周りの修正

SampleComponent というコンポーネントを追加し、page.tsxで読み込ませます

src/components/SampleComponents.tsx
'use client'
 
import { useState } from 'react'
 
export function SampleComponent() {
  const [val, setVal] = useState(0)
 
  return <div>{val}</div>
}
src/app/page.tsx
import Image from 'next/image'
import { SampleComponent } from '@/components/SampleComponent'
 
export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <SampleComponent />
      ・・・


これでESLintを実行してみるとバッチリ怒られます

$ pnpm run lint
> next lint
 
./src/components/SampleComponent.tsx
1:1  Error: Filename is not in kebab case. Rename it to `sample-component.tsx`.  unicorn/filename-case
6:10  Error: The variable `val` should be named `value`. A more descriptive name will do too.  unicorn/prevent-abbreviations
6:15  Error: The variable `setVal` should be named `setValue`. A more descriptive name will do too.  unicorn/prevent-abbreviations
  • 1はファイル名をケバブケースにしよう
  • 2,3はもっと分かりやすい名前にしよう

というものです。



ファイル名はケバブケースではなくキャメルケースで書くことも多いためルール自体offにし、

もう1つの指摘内容は修正していきます

.eslintrc.js
module.exports = {
  extends: ['next/core-web-vitals', 'plugin:unicorn/recommended', 'prettier'],
  rules: {
    // ケバブケース以外のファイル名も許容
    'unicorn/filename-case': 'off',
  },
}
src/components/SampleComponents.tsx
'use client'
 
import { useState } from 'react'
 
export function SampleComponent() {
  const [value, setValue] = useState(0)
 
  return <div>{value}</div>
}


改めてESLintを実行してみると

$ pnpm run lint
> next lint
 
 No ESLint warnings or errors

バッチリです!🙌




余談

アイキャッチは最近ChatGPT先生に作ってもらってまして、

ボツ案としてこんなのも作ってくれました。

ボツになったアイキャッチ向けの画像

いちいち載せたくなるカッコ良さがあるんですよね 😂

プロフィール画像
Yuki Takara
都内でフリーランスのエンジニアをやってます。フロントとアプリ開発メインに幅広くやってます。