Next.jsによるWebアプリケーション開発概論

importを整理するPath Aliasの基本

この節で学ぶこと

この節では、Path Alias(パスエイリアス)とは何か、なぜ import を整理するのに役立つのか、そして Next.js での基本設定方法 を学びます。

Next.js は tsconfig.json / jsconfig.jsonbaseUrlpaths を標準サポートしており、相対パスの代わりに絶対パスや別名パスを使えるようにしています。

公式ドキュメントでは、../../../components/button のような相対 import を @/components/button に置き換える例が示されています。

この節の到達目標は4つです。

  1. Path Alias が「見た目をきれいにするだけの技術」ではなく、ファイル移動や保守のしやすさに関わると理解すること。
  2. baseUrlpaths の役割の違いを説明できること
  3. Next.js でよく使う @/ の設定を読めること。
  4. いつ Alias を使い、いつ相対パスのままでよいかを初心者なりに判断できることです。

そもそも import がなぜ散らかるのか

相対パスは深くなるほど読みにくくなる

最初のうちは、相対パスだけでも問題ありません。

たとえば同じ階層なら、次のように書けます。

import { formatDate } from './formatDate'

これは素直です。

けれど、階層が深くなると話が変わります。

import { Button } from '../../../components/button'

こうなると、読む側はまず ../../../ を数え始めます。

「3つ上がって、そこから components か」と頭の中で地図を描かないといけません。Next.js の公式も、まさにこのような “before / after” の例を示し、@/components/button の形へ整理できると説明しています。

相対パスはファイル移動に弱い

相対パスは、今いる場所から見た位置関係 に依存します。

そのため、ファイルを別フォルダへ動かすと import を大量に直すことがあります。

たとえば、app/dashboard/page.tsx にいたコードを app/admin/dashboard/page.tsx に移すと、../../ の数が変わることがあります。これは初心者にも地味に痛いです。コードの内容は同じなのに、パスだけ大量修正になるからです。

Path Alias は、こうした「場所依存の読みにくさ」をやわらげるための仕組みです。Next.js 公式も、absolute imports and aliases が imports を扱いやすくすると説明しています。

Path Alias とは何か

一言でいえば「import 用の別名」

Path Alias とは、特定のディレクトリへ短い別名を付けて import できるようにする仕組みです。

Next.js 公式では、"paths" を使って module paths を “alias” できると説明されています。TypeScript 公式も paths は custom prefixes を使ってコードを見つけるために resolver へ伝える機能だと説明しています。

たとえば、

import Button from '@/components/button'

この @/ が Alias です。

「この @/ は、実際にはプロジェクトの特定フォルダを指していますよ」と設定で教えているわけです。

何がうれしいのか

うれしい点は主に3つあります。

  1. 見た目が短くなる../../../components/button より @/components/button の方が一目で読めます。
  2. 場所の影響を受けにくい

import 先の基準を一定にできるので、ファイル移動時の修正が減ります。これは Next.js 公式の absolute imports の思想とも合います。

  1. プロジェクトの構造が頭に入りやすい@/components@/lib@/types のように書けると、「このプロジェクトには components や lib がある」と自然に見えてきます。出典なしの補足ですが、実務ではこの可読性がかなり効きます。

baseUrlとpathsの違い

baseUrl は「基準点」

TypeScript 公式では、baseUrl は bare specifier module names を解決するための基準ディレクトリ を設定すると説明しています。たとえば "baseUrl": "./" にすると、hello/world のような import を tsconfig.json と同じ階層から探します。なお TypeScript 公式は、この機能はもともとブラウザの AMD loader 向けで、現在は paths 利用時に必須ではないとも説明しています。

Next.js の公式例では、次のように書いています。

{
  "compilerOptions": {
    "baseUrl": "."
  }
}

この設定があると、たとえば次のような import が可能になります。

import Button from 'components/button'

Next.js 公式でも、baseUrl: "." を使った absolute imports の例としてこの形が示されています。

paths は「別名ルール」

paths は、特定の接頭辞をどのディレクトリへ対応させるか を定義する設定です。Next.js 公式では、"@/components/*": ["components/*"] のように設定し、@/components/button と書ける例を示しています。

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/components/*": ["components/*"]
    }
  }
}

このときの import はこうなります。

import Button from '@/components/button'

つまり、

  • baseUrl は基準点
  • paths は別名の対応表

と考えると、かなり整理しやすいです。

Next.js でよく使う@/の形

create-next-app でも既定値として案内される

Next.js の Installation と create-next-app の CLI ドキュメントでは、推奨デフォルトやカスタマイズ項目の中に import alias @/* が含まれています。create-next-app には --import-alias <alias-to-configure> オプションもあり、既定値は @/* とされています。

つまり、@/ は単なる流行りではなく、Next.js の公式導線でもかなり標準的な形です。

典型的な設定例

src を使わないなら、次のような設定がよくあります。

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  }
}

src を使うなら、基準を src/ に寄せる形もよく見ます。Next.js 公式でも baseUrl: "src/" とし、@/styles/*@/components/*src 配下へ対応させる例が示されています。

{
  "compilerOptions": {
    "baseUrl": "src/",
    "paths": {
      "@/components/*": ["components/*"],
      "@/styles/*": ["styles/*"]
    }
  }
}

このとき、src/components/Button.tsx は次のように import できます。

import Button from '@/components/Button'

まずは before / after を見てみる

Alias なし

import Header from '../../../components/layout/Header'
import Footer from '../../../components/layout/Footer'
import { formatDate } from '../../../lib/formatDate'

読めなくはありません。

でも、どこまで戻っているのかを毎回追う必要があります。

Alias あり

import Header from '@/components/layout/Header'
import Footer from '@/components/layout/Footer'
import { formatDate } from '@/lib/formatDate'

こちらは、どこから見ても同じ基準 で読めます。

ファイルを今どの階層から開いているかに左右されません。Next.js 公式もこの読みやすさを狙って aliases を紹介しています。

TypeScript 的に気をつけること

paths は TypeScript に「そう解釈して」と教えているだけ

TypeScript 公式は非常に重要な注意を書いています。

pathstsc が import の出力自体を書き換えるわけではない、あくまで「別のツールがこの対応を理解して処理する」と TypeScript へ知らせるための設定だ、と説明しています。

これは初心者には少し難しく見えますが、要するにこうです。

  • TypeScript は「この alias はこの場所だ」と理解する
  • 実際の実行やバンドルでは、Next.js などのツール側もその対応を理解している必要がある Next.js は baseUrlpaths を built-in support しているので、通常の Next.js プロジェクトではここを過度に心配しなくて大丈夫です。

baseUrl は万能ではない

TypeScript 公式では、baseUrlnode_modules より高い優先度で解決されること、そして現在では paths 利用時に必須ではないことが説明されています。さらに、この機能は他用途には推奨されない文脈もあります。

ここから言えるのは、何でもかんでも baseUrl だけで解決しようとしない方がよい ということです。 初心者の段階では、Next.js の公式例の範囲で使うのが安全です。

Alias をどう設計するか

最初は @/ だけで十分

初心者が最初から @components@lib@hooks@utils と細かく分けすぎると、かえって覚えることが増えます。 まずは @/ ひとつで十分です。

import Button from '@/components/Button'
import { fetchUser } from '@/lib/fetchUser'
import type { User } from '@/types/User'

これだけでもかなり読みやすくなります。

Next.js の create-next-app でも既定値として @/* が案内されているので、最初の学習としても自然です。

細かく切るのは構造が固まってから

プロジェクトが大きくなると、個別 alias を切りたくなることがあります。

たとえば次のような形です。

{
  "compilerOptions": {
    "baseUrl": "src/",
    "paths": {
      "@/components/*": ["components/*"],
      "@/lib/*": ["lib/*"],
      "@/types/*": ["types/*"]
    }
  }
}

これは悪くありません。

ただ、プロジェクト構造がまだ流動的なうちは、まず @/ 一括で始める方が混乱しにくいことも多いです。これは実務上の判断ですが、初学者にも有効です。出典なしの補足です。

相対パスの方がよい場面もある

同じフォルダ、近いフォルダなら相対でも十分

Path Alias は便利ですが、すべての import を機械的に alias 化すればよいわけではありません。

たとえば同じフォルダ内の import は、次のように相対で十分分かりやすいこともあります。

import { add } from './add'
import { subtract } from './subtract'

このようなケースまで無理に alias にすると、逆に「同じフォルダなのに遠回りしている」感じも出ます。

実務では「遠い場所は alias、近い場所は相対」のような使い分けをすることがあります。出典なしですが、かなり一般的な設計感覚です。

実際に設定してみる

tsconfig.json に追加する例

Next.js で src を使う構成を想定すると、こう書けます。

{
  "compilerOptions": {
    "target": "ES2017",
    "lib": ["dom", "dom.iterable", "esnext"],
    "strict": true,
    "baseUrl": "src/",
    "paths": {
      "@/*": ["*"]
    }
  }
}

この設定なら、src/components/Button.tsx@/components/Button として import できます。src/lib/fetcher.ts なら @/lib/fetcher です。

使用例

import Button from '@/components/Button'
import { fetcher } from '@/lib/fetcher'

export default function Page() {
  return (
    <main>
      <h1>Path Alias の確認</h1>
      <Button />
    </main>
  )
}

このコードを見たときに、「これはプロジェクトの componentslib を見に行っているのだな」とすぐ想像できれば成功です。

初心者がつまずきやすい点

1. @/ の先がどこなのか分からなくなる

これはかなりよくあります。

解決策は単純で、tsconfig.jsonpaths を見に行く癖を付ける ことです。Alias の正体はそこに書いてあります。Next.js 公式も alias 設定を tsconfig.json / jsconfig.json に書く形で説明しています。

2. src を使うかどうかで基準が変わる

baseUrl: "."baseUrl: "src/" は意味が違います。

前者はプロジェクトルート基準、後者は src 基準です。Next.js 公式の例でもこの違いが示されています。

3. 何でも Alias にしたくなる

Alias は便利ですが、使いすぎると逆にルールが増えます。

最初は @/ ひとつで十分です。これは公式の default import alias にも合っています。

練習問題

問1

Path Alias の主な目的として最も適切なものはどれですか。

A. 画像サイズを自動圧縮する

B. import パスを短くし、分かりやすくする

C. データベースを自動作成する

D. CSS を自動生成する

答え

B

解説

Next.js 公式では、absolute imports and module aliases によって ../../../components/button のような import を @/components/button に整理できると説明しています。

問2

Next.js の create-next-app で、既定の import alias として案内されているものはどれですか。

A. #/ B. ~/ C. @/* D. $/*

答え

C

解説

Next.js の Installation と create-next-app CLI ドキュメントでは、既定の import alias は @/* とされています。

問3

paths の役割として正しいものはどれですか。

A. TypeScript の型チェックを完全に無効化する

B. import 用の別名と実際のパス対応を定義する

C. ブラウザ履歴を保存する

D. Node.js のバージョンを固定する

答え

B

解説

Next.js 公式は paths により module paths を alias できると説明しています。TypeScript 公式も custom prefixes を解決するための設定だと説明しています。

問4

TypeScript 公式が paths について注意している内容として正しいものはどれですか。

A. pathstsc が import 文字列そのものを自動で書き換える B. paths は TypeScript に解決方法を伝えるが、別ツール側の対応も必要になる C. paths を使うと node_modules が不要になる D. paths は CSS 専用機能である

答え

B

解説

TypeScript 公式は、pathstsc が出力する import パス自体を変えるものではなく、別ツールがその対応を使う前提で TypeScript に知らせるための機能だと説明しています。

問5

src ディレクトリを使う構成で、src/components/Button.tsx@/components/Button として読みたい場合、よくある設定として適切なのはどれですか。

A. "baseUrl": "src/" とし、"@/*": ["*"] を設定する B. "baseUrl": "public/" とする C. paths を空にする D. package.json にだけ書く

答え

A

解説

Next.js 公式では、baseUrl: "src/" を基準に @/components/*@/styles/*src 配下へ対応させる例が示されています。

まとめ

Path Alias の本質は、単に見た目を整えることではありません。

プロジェクト全体の import の基準をそろえ、読みやすさと保守性を上げることです。Next.js は baseUrlpaths を built-in support しており、create-next-app でも @/* が既定の alias として案内されています。

この節でまず覚えたいのは次の4点です。

  • ../../../... のような深い相対パスは読みにくくなりやすい。
  • baseUrl は基準点、paths は別名ルールである。
  • Next.js では @/ が標準的な alias としてよく使われる。
  • まずは @/ ひとつから始めれば十分である。これは公式導線とも相性がよいです。

ここが分かると、import の行を見たときのストレスがかなり減ります。

そしてそれは、地味ですが大きいです。コードは1行ずつ読むものなので、その1行が素直に読めることは、積み重なると相当効いてきます。

参考文献

  • Next.js Documentation, Getting Started: Installation.
  • Next.js Documentation, CLI: create-next-app.
  • Next.js Documentation, Absolute Imports and Module Path Aliases.
  • TypeScript Documentation, TSConfig Option: baseUrl.
  • TypeScript Documentation, TSConfig Option: paths.
教材トップへ戻る