🙆‍♀️

Next.jsのファイル名をeslint-plugin-validate-filenameで命名規則を作成する

2024/05/07に公開

こんにちはhiro08です。

長期休みを利用して、ファイルの命名規則をLintで検証するライブラリを作成してみました。興味のある方は、ぜひPRやスターを頂ければ嬉しいです。

https://github.com/hiro08gh/eslint-plugin-validate-filename

作成したモチベーションとして、フロントエンド環境のファイル名にはプロジェクトによって、暗黙の命名ルールが多いことにあります。

例えば、一般的にコンポーネントファイルはパスカルケースですが、apiやutility関連のファイルはキャメルケースで作成する、またはHooksの処理はファイル名の頭にuseを付けるなどがあげられます。

フロントエンド環境に限らず、みなさまの周りにも暗黙の命名ルールが存在するのではないでしょうか?

この辺りを暗黙のルールとせず、プロジェクトによって命名ルールをLintで縛れたらいいよね、という発想から公開に至りました。

今回は2つのLintルールを元にNext.jsプロジェクトのファイル名のルールを作成してみます。

インストール

まず初めに必要なパッケージをインストールします。

npm install --save-dev eslint-plugin-validate-filename

そして、ESLintの設定に追加します。これで準備は完了です。

{
  "plugins": ["validate-filename"]
}

validate-filename

eslint-plugin-validate-filenameでは2つのルールを作成しました。それが、naming-ruleslimit-extensionsです。

validate-filename/naming-rules

naming-rulesでは各フォルダを対象に、case (パスカルケース、キャメルケース etc...) や、patterns (正規表現でファイルのフォーマットを指定) を設定することができます。下記ルールではhooksディレクトリ配下のファイルを対象に、キャメルケースで先頭にuseが付く命名のみ有効となります。

{
  "rules": {
    "validate-filename/naming-rules": [
      "error",
      {
        rules: [
          {
            case: 'camel',
            target: "**/hooks/**",
            patterns: '^use',
          }
        ] 
      }
    ],
}

有効と無効のケースの例です。

/hooks/useHooks.tsx // valid
/hooks/hooks.tsx // invalid
/hooks/Hooks.tsx // invalid

validate-filename/limit-extensions

limit-extensionsでは各フォルダを対象に拡張子を検証します。下記ルールでは、componentsフォルダは.tsx.tsの拡張子のみ有効としています。

{
  "rules": {
    "validate-filename/limit-extensions": [
      "error",
      {
        rules: [
          {
            target: "**/components/**",
            extensions: ['.tsx', '.ts'],
          }
        ]
      }
    ],
}

こちらは有効と無効の例になります。

/components/App.tsx // valid
/components/App.ts // valid
/components/App.vue // invalid

Next.jsプロジェクトで実践

今回作成した2つのルールについて説明しました。このルールを使ってNext.jsのプロジェクトでどう活かせるかを説明していきます。

components配下の命名規則

コンポーネントを作成する際、命名には PascalCase を使用することをお勧めします。この規約は、コンポーネントと標準的なHTML要素を簡単に区別するのに役立ちます。

caseには、camel、pascal、snake、kebab、flat.があり、targetにはフォルダパスの名前を指定します。 インデックス名は無視されます。

{
  "case": "pascal",
  "target": "**/components/**"
}

こちらは有効と無効の例になります。

/components/App/App.tsx // valid
/components/App/app.tsx // invalid

appディレクトリーの命名規則

Next.jsのappディレクトリ配下は、ケバブケースで作成します。実際に具体的なファイル名は決まっていて、すべてケバブケースだからです。
https://nextjs.org/docs/app/api-reference/file-conventions

{
  "case": "kebab",
  "target": "**/app/**",
}

こちらは有効と無効の例になります。

/app/page.tsx // valid
/app/not-found.tsx //valid
/app/appRoute.tsx //invalid

appディレクトリ内の特定のファイル名に使用を制限したい場合は、patternsでルールを設定することで実現できる。

{
  "case": "kebab",
  "target": "**/app/**",
  "patterns": "^(page|layout|loading|error|not-found|route|template).tsx$"
}

Hooksの命名規則

Hooksディレクトリの下で、ファイル名にuseを追加します。useを入れることで、そのファイルにHooksのロジックが含まれていることを示します。

{
  "case": "camel",
  "target": "**/hooks/**",
  "patterns": "^use"
}

こちらは有効と無効の例になります。

/hooks/useHooks.ts // valid
/hooks/hooks.tsx // invalid

Providerも同じような設定をすることができます。

{
  "case": "camel",
  "target": "**/providers/**",
  "patterns": "^[a-zA-Z]*Provider"
}

最後に

ファイルの命名規則に関する ESLint のルールを実装することで、 プロジェクトのクリーンさ、可読性、保守性が向上します。フロントエンド開発では暗黙の命名規則が数多く存在するため、eslint-plugin-validate-filenameを使って検証することをお勧めします。

https://github.com/hiro08gh/eslint-plugin-validate-filename

最終的な設定

{
  "plugins": ["validate-filename"],
  "rules": {
    "validate-filename/naming-rules": [
      "error",
      {
        "rules": [
          {
            "case": "pascal",
            "target": "**/components/**"
          },
          {
            "case": "kebab",
            "target": "**/app/**",
            "patterns": "^(page|layout|loading|error|not-found|route|template).tsx$"
          },
          {
            "case": "camel",
            "target": "**/hooks/**",
            "patterns": "^use"
          },
          {
            "case": "camel",
            "target": "**/providers/**",
            "patterns": "^[a-zA-Z]*Provider"
          }
        ]
      }
    ]
  }
}

Discussion