フラグメントの基本(th:fragment)を完全ガイド!初心者でもわかる基本的な使い方
新人
「Spring MVCでHTMLの共通部分を効率よく管理する方法ってありますか?」
先輩
「Thymeleafのth:fragmentを使うと、共通部分をフラグメントとして定義して、再利用できるんだ。」
新人
「フラグメントって何ですか?どうやって使うんですか?」
先輩
「じゃあ、基本から順番に説明していこう!」
1. フラグメントとは?
フラグメントとは、HTMLの特定の部分を再利用できるように切り出したコードのことです。Webアプリケーションでヘッダーやフッター、サイドバーなどの共通部分を一つのファイルにまとめておくことで、複数のページで同じコードを繰り返し書く手間を省けます。これにより、コードの可読性が向上し、保守性も高まります。
2. th:fragmentとは何か?
th:fragmentは、Thymeleafでフラグメント(再利用可能なテンプレートの部分)を定義するための属性です。共通するレイアウト部分を別ファイルにまとめ、他のHTMLテンプレートから呼び出して使用できます。これにより、HTMLコードの重複を減らし、メンテナンスを簡単にします。
【フラグメント定義の例】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>共通レイアウト</title>
</head>
<body>
<header th:fragment="siteHeader">
<h1>サイト共通ヘッダー</h1>
<nav>
<a th:href="@{'/home'}">ホーム</a>
<a th:href="@{'/about'}">紹介</a>
</nav>
</header>
</body>
</html>
上記コードでは、<header>タグにth:fragment="siteHeader"を設定することで、「siteHeader」という名前のフラグメントを定義しています。これにより、他のHTMLファイルからこのヘッダーを簡単に呼び出して使用できます。
3. th:fragmentを使うメリット
- コードの再利用性向上: ヘッダーやフッターをフラグメントとして定義することで、複数のHTMLファイルで再利用できます。
- 保守性の向上: 共通部分を修正する際に、フラグメントファイルだけ変更すればすべてのページに反映されます。
- 開発効率の向上: 重複コードをなくし、開発時間を短縮できます。
- 可読性の改善: ページごとのHTMLがシンプルになり、読みやすくなります。
特に、大規模なWebアプリケーション開発においては、ページ数が多くなるほどフラグメントの効果が顕著になります。th:fragmentを使うことで、Spring MVCとThymeleafを組み合わせた開発がよりスムーズになります。
4. th:fragmentを使った基本的なフラグメントの作成と読み込み実例
th:fragmentを使うことで、HTMLの特定の部分をフラグメントとして切り出し、他のテンプレートから簡単に読み込んで再利用できます。ここでは、基本的なフラグメントの作成と読み込み方法を紹介します。
【フラグメントの作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>共通フラグメント</title>
</head>
<body>
<div th:fragment="commonHeader">
<header>
<h1>共通ヘッダー</h1>
<nav>
<a th:href="@{'/home'}">ホーム</a>
<a th:href="@{'/about'}">紹介</a>
<a th:href="@{'/contact'}">お問い合わせ</a>
</nav>
</header>
</div>
</body>
</html>
この例では、commonHeaderという名前でフラグメントを定義しています。ヘッダー部分を複数のページで使い回すことができます。
【フラグメントの読み込み方法】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>トップページ</title>
</head>
<body>
<div th:replace="'fragments/common' :: commonHeader"></div>
<main>
<h2>ようこそ!</h2>
<p>こちらはトップページです。</p>
</main>
</body>
</html>
th:replaceを使用して、先ほど作成したcommonHeaderフラグメントを読み込んでいます。これにより、共通のヘッダーが簡単に挿入され、コードの重複を防げます。
5. th:fragmentのパラメータ渡し方法
th:fragmentは、パラメータを渡してフラグメントの表示内容を動的に変更できます。これにより、同じフラグメントでも異なるデータを表示できるようになります。
【パラメータ付きフラグメントの作成】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>パラメータ付きフラグメント</title>
</head>
<body>
<div th:fragment="greeting(name)">
<p>こんにちは、<span th:text="${name}"></span>さん!</p>
</div>
</body>
</html>
上記のコードでは、greetingというフラグメントにnameパラメータを定義しています。
【パラメータを渡してフラグメントを呼び出す】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>パラメータ使用例</title>
</head>
<body>
<div th:replace="'fragments/greeting' :: greeting('田中')"></div>
<div th:replace="'fragments/greeting' :: greeting('山田')"></div>
</body>
</html>
この例では、田中や山田というパラメータをフラグメントに渡しています。これにより、呼び出すたびに異なるメッセージを表示できます。
6. th:fragmentを使ったヘッダー・フッターの共通化
大規模なWebアプリケーションでは、ヘッダーやフッターをフラグメントで共通化することで、開発効率と保守性が向上します。ここでは、ヘッダーとフッターの共通化の方法を解説します。
【ヘッダーとフッターのフラグメント定義】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>共通パーツ</title>
</head>
<body>
<header th:fragment="siteHeader">
<h1>サイト共通ヘッダー</h1>
<nav>
<a th:href="@{'/home'}">ホーム</a>
<a th:href="@{'/about'}">紹介</a>
<a th:href="@{'/contact'}">お問い合わせ</a>
</nav>
</header>
<footer th:fragment="siteFooter">
<p>© 2024 サンプルサイト</p>
</footer>
</body>
</html>
ここでは、siteHeaderとsiteFooterの2つのフラグメントを定義しています。
【フラグメントの呼び出し方法】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>共通化されたページ</title>
</head>
<body>
<div th:replace="'fragments/common' :: siteHeader"></div>
<main>
<h2>ページの内容</h2>
<p>これはメインコンテンツです。</p>
</main>
<div th:replace="'fragments/common' :: siteFooter"></div>
</body>
</html>
このように、各ページでヘッダーとフッターを呼び出すことで、共通部分を簡単に挿入できます。変更が必要な場合も、フラグメントファイルを修正するだけで全ページに反映されるため、保守が非常に楽になります。
7. th:fragmentを使う際のよくあるエラーとその対処法
th:fragmentを使う際に初心者がよく遭遇するエラーと、その解決方法を解説します。Spring MVCとThymeleafを組み合わせた開発では、フラグメントの呼び出し方やパラメータの渡し方でミスが起こりやすいので、しっかり理解しておきましょう。
【エラー1: フラグメントが見つからない】
原因の一つに、th:replaceやth:includeで指定するパスが間違っている場合があります。ファイルの場所やファイル名を確認しましょう。
<div th:replace="'fragments/layout' :: siteHeader"></div>
例えば、fragments/layout.htmlがtemplates/fragments/ディレクトリ内に存在しない場合、フラグメントが見つからないエラーが発生します。正しいパスを指定してください。
【エラー2: パラメータの未渡しエラー】
パラメータ付きフラグメントを呼び出す際に、パラメータが正しく渡されていないとエラーになります。
<div th:replace="'fragments/greeting' :: greeting"></div> <!-- パラメータ未渡しエラー -->
このようにパラメータを指定し忘れると、Exception evaluating SpringEL expressionのようなエラーが出ます。必ずパラメータを渡しましょう。
<div th:replace="'fragments/greeting' :: greeting('田中')"></div> <!-- 正しい呼び出し方 -->
【エラー3: th:fragmentのスコープ問題】
フラグメント内で参照している変数が、呼び出し元のテンプレートで定義されていない場合もエラーが発生します。呼び出す側でモデルに必要なデータを含めておきましょう。
8. th:fragmentを使ったベストプラクティスと注意点
フラグメントを使用することで、共通部分の管理や再利用が簡単になりますが、効率的に利用するためにはいくつかのポイントを押さえる必要があります。ここでは、th:fragmentを使う際のベストプラクティスと注意点を紹介します。
【ベストプラクティス1: ファイル構成を整理する】
フラグメント用のHTMLファイルはtemplates/fragmentsディレクトリにまとめることで、可読性が向上します。
templates/
├── fragments/
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
└── pages/
├── home.html
└── about.html
このようにディレクトリを整理することで、フラグメントの管理が容易になります。
【ベストプラクティス2: th:replaceとth:includeの使い分け】
- th:replace: フラグメント全体を置き換える場合に使用します。
- th:include: フラグメントの中身を現在のタグ内に挿入する場合に使用します。
<!-- 置き換え (th:replace) -->
<div th:replace="'fragments/header' :: siteHeader"></div>
<!-- 挿入 (th:include) -->
<div th:include="'fragments/sidebar' :: siteSidebar"></div>
一般的に、レイアウト共通部分にはth:replaceを使うのが推奨されます。
【注意点: 不要なネストを避ける】
フラグメントを多用しすぎると、HTMLが深くネストされて読みづらくなります。必要以上の入れ子構造は避け、シンプルな構成を心がけましょう。
9. 実践!共通レイアウトを作成して再利用性を高めるアプリの作成例
最後に、実際にth:fragmentを使って共通レイアウトを作成し、複数ページで再利用する簡単なSpring MVCアプリを作成してみましょう。
【プロジェクト構成】
src/main/resources/templates/
├── fragments/
│ ├── header.html
│ ├── footer.html
│ └── layout.html
└── pages/
├── home.html
└── about.html
【header.html】
<header th:fragment="siteHeader">
<h1>共通ヘッダー</h1>
<nav>
<a th:href="@{'/home'}">ホーム</a>
<a th:href="@{'/about'}">紹介</a>
<a th:href="@{'/contact'}">お問い合わせ</a>
</nav>
</header>
【footer.html】
<footer th:fragment="siteFooter">
<p>© 2024 サンプルサイト</p>
</footer>
【layout.html】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${title}">共通レイアウト</title>
</head>
<body>
<div th:replace="'fragments/header' :: siteHeader"></div>
<main th:insert="~{::body}"></main>
<div th:replace="'fragments/footer' :: siteFooter"></div>
</body>
</html>
【home.html】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="'fragments/layout'">
<head>
<title>ホームページ</title>
</head>
<body>
<h2>ホームへようこそ!</h2>
<p>これはホームページの内容です。</p>
</body>
</html>
【about.html】
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" th:replace="'fragments/layout'">
<head>
<title>紹介ページ</title>
</head>
<body>
<h2>当サイトについて</h2>
<p>こちらは紹介ページです。</p>
</body>
</html>
【コントローラ (HomeController.java)】
@Controller
public class HomeController {
@GetMapping("/home")
public String home(Model model) {
model.addAttribute("title", "ホームページ");
return "pages/home";
}
@GetMapping("/about")
public String about(Model model) {
model.addAttribute("title", "紹介ページ");
return "pages/about";
}
}
このように、フラグメントを使用して共通レイアウトを作成することで、全ページで同じ構造を持ちつつ、各ページの内容を簡単に差し替えられます。これにより、メンテナンス性が向上し、新たなページ追加時も効率的に作業が進められます。
まとめ
今回の記事では、Thymeleafのth:fragmentを使ったフラグメント機能について、基本から応用まで順を追って整理しました。Webアプリケーションの開発では、ページ全体の構造やデザインを統一しながら、必要な部分だけを柔軟に変更していくことが求められます。その中で、ヘッダーやフッター、サイドバーなどの共通部分を毎回同じように書き続けると、コードが増え続けて管理が複雑になりがちです。そこで、Thymeleafが用意しているフラグメント機能を活用することで、HTMLの共通パーツをひとつの場所にまとめ、複数ページで再利用できるようになり、保守性や可読性を大きく高めることができました。
th:fragmentを使えば、よく利用されるヘッダー・フッター・ナビゲーションなどを専用ファイルに切り出して管理でき、修正時にはフラグメントファイルだけを変更するだけで、すべてのページに反映させられるため、効率的な開発が可能です。また、ページごとに表示内容を変えたいときには、フラグメントにパラメータを渡すことで動的にテキストを変更できる点も非常に便利でした。さらに、th:replaceやth:includeなどの属性を組み合わせることで、ページレイアウト全体を柔軟に構築でき、Spring MVCとの組み合わせによって、実際の画面表示を想定した設計が自然に行えます。
例えば、以下のようにフラグメントを定義し、再利用することでレイアウトを統一できます。
<header th:fragment="siteHeader">
<h1>サイト共通ヘッダー</h1>
<nav>
<a th:href="@{'/home'}">ホーム</a>
<a th:href="@{'/about'}">紹介</a>
<a th:href="@{'/contact'}">お問い合わせ</a>
</nav>
</header>
<div th:replace="'fragments/header' :: siteHeader"></div>
このように、フラグメントを使えば複数ページで同じヘッダーを使用でき、コードを繰り返し書く必要がありません。フッターも同様にフラグメント化すれば、サイト全体の統一感が保たれるうえに、デザイン変更時の手間も減ります。
実践で意識したいフラグメント活用のポイント
フラグメントを使う際には、ファイル構成をわかりやすく整理しておくことが重要です。たとえば、templates/fragmentsディレクトリを用意し、ヘッダー・フッター・サイドバーなどをひとつのフォルダに集めておけば、あとから追加や変更が必要になった場合でも迷うことなく編集できます。また、フラグメント内で利用する変数は、呼び出し元でモデルに含まれているかを確認し、不足によるエラーを防ぐ必要があります。
パラメータを渡すフラグメントも便利で、次のように名前を変えて表示内容を変えることができます。
<div th:fragment="greeting(name)">
<p>こんにちは、<span th:text="${name}"></span>さん!</p>
</div>
<div th:replace="'fragments/greeting' :: greeting('佐藤')"></div>
このようにフラグメントの使い方を覚えておくと、テンプレートファイルの整理が驚くほどスムーズになり、ページ追加時も最小限の労力で済みます。特に、Spring MVCやThymeleafを使ったWebアプリケーションでは、共通レイアウトを作ることが必須となるため、フラグメントを使いこなすことが大きな近道になります。
新人
「フラグメントを使うと、ヘッダーやフッターを一か所にまとめて管理できるのが便利ですね。ファイルを開く量も減って作業が楽になりそうです。」
先輩
「そうだね。同じ部分を何度も書く必要がなくなるだけで、時間もミスも減るよ。修正するときもフラグメントのファイルだけ直せば全ページに反映されるから効率がいいんだ。」
新人
「パラメータ付きフラグメントも活用すれば、動的な表示もできますし、汎用性が高いですね。レイアウトの統一にも役立ちそうです。」
先輩
「その通り。項目ごとに共通部分を整理しておけば、さらに作業しやすい構成を作れる。プロジェクトが大きくなるほど効果が大きくなるから、今のうちに慣れておくと良いよ。」
新人
「はい!フラグメントの仕組みをしっかり活用して、今後のプロジェクトでも効率よく作業できるようにします。」