Thymeleaf JavaScript 外部ファイル連携の書き方を初心者向けに徹底解説!
新人
「先輩、ThymeleafでJavaScriptと連携するときって、外部ファイルに分けた方がいいんですか?」
先輩
「うん、いい質問だね。ThymeleafでHTMLテンプレートを作るとき、JavaScriptを外部ファイルに分けると保守性が上がるし、複数ページで共通処理を使い回せるんだ。」
新人
「なるほど。HTML内に直接JavaScriptを書くよりも、外部にした方がいいってことですね。でも、Thymeleafの変数を外部ファイルで使うのって難しそうです…」
先輩
「確かに最初は少しややこしいけど、ThymeleafとJavaScriptの“外部ファイル連携”を正しく理解すれば、すぐに使いこなせるようになるよ。順番に見ていこう!」
1. Thymeleafとは?
まずは、Thymeleaf(タイムリーフ)の基本をおさらいしておきましょう。Thymeleafは、Spring BootなどのJavaアプリケーションで使われるテンプレートエンジンです。テンプレートエンジンとは、HTMLファイルの中にサーバー側のデータを動的に埋め込むための仕組みのことです。
例えば、Thymeleafを使えば、Javaのコントローラで設定した値を、HTMLの中に直接反映させることができます。次のようなシンプルな例を見てみましょう。
<p th:text="${message}">ここにメッセージが表示されます</p>
このように書くと、Springの@Controllerで渡したmessageという変数の内容が、HTML上に反映されます。Thymeleafは「HTMLテンプレート+Javaの値」を組み合わせて動的なWebページを生成できるため、JavaのWeb開発では非常に人気があります。
また、pleiadesでGradle構成を使えば、環境構築も簡単です。MavenではなくGradleで依存関係を管理し、プロジェクト作成時に「Spring Web」と「Thymeleaf」をチェックするだけでOKです。これでThymeleafが使える環境が整います。
2. JavaScript外部ファイルとThymeleafの連携が必要になる理由
次に、なぜThymeleafとJavaScriptの“外部ファイル連携”が重要なのかを理解しましょう。通常、JavaScriptをHTMLに直接書くこともできますが、実際の開発では次のような問題が出てきます。
- HTMLファイルが長くなり、見通しが悪くなる
- 複数の画面で同じJavaScript処理を共有できない
- Thymeleafの変数をスクリプト内で使うときに、記述が煩雑になる
そのため、多くの開発現場では、JavaScriptを別ファイルに分離し、ThymeleafのHTMLテンプレートからそのファイルを呼び出す方法を使います。例えば、次のようにして外部JSファイルを読み込みます。
<script th:src="@{/js/sample.js}"></script>
上記のように、Thymeleafのth:src属性を使うことで、プロジェクト内のstatic/jsフォルダにあるsample.jsを動的に読み込むことができます。Thymeleafのテンプレートエンジンが自動でパスを解決してくれるため、環境に依存せずJSファイルを参照できます。
また、@Controllerで渡したデータをJavaScriptで使うケースもよくあります。例えば、Java側でユーザー情報を取得しておき、JSで画面操作に反映させるといった流れです。これを実現するには、ThymeleafとJavaScriptの“値渡し”を理解する必要があります。
@Controller
public class UserController {
@GetMapping("/user")
public String userPage(Model model) {
model.addAttribute("userName", "山田太郎");
return "user";
}
}
このように、SpringのコントローラでuserNameという変数を追加しておきます。これをHTML側でThymeleafを通じて埋め込み、JavaScriptでも使えるようにするわけです。
ただし、外部ファイルの場合は、単純に${userName}のような式をそのまま使うことはできません。なぜなら、外部JSファイルはサーバーではなくブラウザで読み込まれるため、Thymeleafによる変数展開が行われないからです。
そのため、まずHTMLテンプレート上でJavaScript変数に値を埋め込み、その変数を外部ファイルから参照するという構成を取るのが基本です。次回の記事(中盤部分)では、この「Thymeleafテンプレートから外部JavaScriptファイルへ値を渡す」具体的な方法を詳しく見ていきます。
3. Thymeleafテンプレートから外部JavaScriptファイルを読み込む方法(th:srcの使い方)
ここからは、Thymeleafのテンプレートで外部JavaScriptファイルを読み込む方法を具体的に見ていきましょう。Thymeleafでは、HTMLのscriptタグに対してth:src属性を指定することで、Spring Bootのstaticディレクトリ内にあるJavaScriptファイルを簡単に読み込むことができます。
<script th:src="@{/js/user.js}"></script>
このように書くと、src/main/resources/static/js/フォルダ内のuser.jsが自動的に読み込まれます。Thymeleafのth:src属性は、アプリケーションのコンテキストパスを考慮してURLを生成するため、環境が変わってもファイルパスの修正が不要になります。
例えば、開発環境と本番環境でアプリケーションのパスが異なる場合でも、@{/js/user.js}の形式で指定すれば、正しいパスを自動で組み立ててくれるのです。これがThymeleafの大きな利点です。
また、外部JavaScriptファイルを読み込む位置にも注意が必要です。多くのケースでは、HTMLの最後、つまり</body>タグの直前に記述します。これにより、HTML要素の読み込みが完了してからJavaScriptが実行されるため、DOM操作がスムーズに行えます。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザー情報</title>
</head>
<body>
<h1 th:text="'こんにちは、' + ${userName} + 'さん!'"></h1>
<!-- 外部JSの読み込み -->
<script th:src="@{/js/user.js}"></script>
</body>
</html>
この構成を守ることで、Thymeleafテンプレートと外部JavaScriptの連携が正しく動作します。ここまでで、外部ファイルの読み込み方法が理解できましたね。次は、実際に「コントローラで渡した値を外部JavaScriptで使う」方法を見ていきましょう。
4. コントローラから渡した値を外部JavaScriptで扱う仕組み
Thymeleafの大きな特徴のひとつが、Springの@Controllerで渡した値をHTML上で簡単に使えることです。しかし、外部JavaScriptファイルではそのままThymeleaf変数を参照することはできません。なぜなら、外部ファイルはサーバーではなくクライアント(ブラウザ)側で読み込まれるためです。
そこで一般的に行われるのが、「Thymeleafのテンプレート内でJavaScript変数に値を埋め込み、外部ファイルからその変数を利用する」という方法です。まずは、コントローラで値を設定します。
@Controller
public class UserController {
@GetMapping("/user/info")
public String showUserInfo(Model model) {
model.addAttribute("userName", "佐藤花子");
model.addAttribute("userAge", 28);
return "user_info";
}
}
次に、Thymeleafテンプレート側でこの値をJavaScript変数として定義します。
<script th:inline="javascript">
const userData = {
name: [[${userName}]],
age: [[${userAge}]]
};
</script>
<script th:src="@{/js/userInfo.js}"></script>
ここでのポイントは、th:inline="javascript"を指定することです。これにより、ThymeleafはJavaScriptの構文に合わせてサーバー変数を展開してくれます。さらに、二重角括弧([[ ]])を使うことで、JavaScript用にエスケープされた安全な形式で値を出力できます。
この状態でHTMLをブラウザで開くと、次のようなJavaScriptコードが生成されています。
const userData = {
name: "佐藤花子",
age: 28
};
このuserData変数を外部のuserInfo.jsで参照できるようになります。例えば次のようにして使えます。
// static/js/userInfo.js
console.log("ユーザー名:", userData.name);
console.log("年齢:", userData.age);
このように、外部JavaScriptファイルでuserDataオブジェクトを参照すれば、Thymeleafで渡した値を動的に扱うことができます。これが「ThymeleafからJavaScriptへの値渡し」の基本的な流れです。
5. 外部JSでThymeleaf変数を使うときの注意点(スコープとレンダリングの関係)
最後に、Thymeleaf変数を外部JavaScriptファイルで使うときの注意点を見ておきましょう。よくある誤解は、外部JavaScriptの中で[[${変数}]]のように書けば値が展開されると思ってしまうことです。しかし、それは動作しません。
理由は、Thymeleafの変数展開はHTMLテンプレートのレンダリング時にサーバー側で行われるためです。外部JSファイルはサーバー処理を経由せず、ブラウザから直接読み込まれるため、Thymeleafタグを認識しないのです。
したがって、次のように外部ファイル内で直接Thymeleaf式を書いても、実際にはブラウザにそのまま出力されてしまいます。
// 間違った例:Thymeleafは外部JSでは展開されない
const name = [[${userName}]];
これを避けるには、前の章で紹介したように、HTML側でJavaScript変数にサーバーの値を埋め込んでから外部ファイルで利用するのが正解です。
また、スコープにも注意が必要です。HTMLで定義したJavaScript変数がconstやletで定義されている場合、その変数はブロックスコープ内に閉じ込められる可能性があります。外部ファイルからアクセスできるようにするには、グローバルスコープ(windowオブジェクト)に変数を設定するのが安全です。
<script th:inline="javascript">
window.userData = {
name: [[${userName}]],
age: [[${userAge}]]
};
</script>
<script th:src="@{/js/userInfo.js}"></script>
このように書くと、外部ファイル内でwindow.userDataとしてアクセスできるため、スコープの問題を避けられます。
// 外部ファイルで参照可能
console.log(window.userData.name);
この方法を使えば、Thymeleafのテンプレートで定義したデータを外部JavaScriptファイルから確実に利用できます。さらに、レンダリング済みのHTML内で値を確認したいときは、ブラウザの開発者ツールでコンソールを開き、変数が正しく渡されているか確認してみましょう。
ここまでで、ThymeleafとJavaScriptの外部ファイル連携の基本的な仕組みが理解できたと思います。次回の記事では、これをさらに発展させて、動的な処理や安全なデータの扱い方について詳しく解説していきます。
6. 外部JavaScriptで安全に値を扱うポイント(スクリプトインジェクション対策)
ここからは、外部JavaScriptファイルでThymeleafの値を扱う際に注意すべき「安全性」のポイントを見ていきましょう。特に初心者がつまずきやすいのが、スクリプトインジェクションという脆弱性です。これは、サーバーから渡された値に悪意あるスクリプトが混入している場合、意図せずJavaScriptとして実行されてしまう問題です。
Thymeleafでは、このような危険を防ぐためにエスケープ処理が自動で行われます。特にJavaScript内で値を出力する場合は、[[${変数}]]のように二重角括弧で囲む書き方が重要です。これにより、Thymeleafがスクリプトとして解釈されないように変換してくれます。
<script th:inline="javascript">
const safeValue = [[${userInput}]];
</script>
上記のように書くことで、もしuserInputに特殊な文字列が入っていても、Thymeleafが安全な形式に変換してくれます。これを通常の${}で出力してしまうと、HTML上でスクリプトがそのまま展開されてしまい、セキュリティリスクが発生します。
また、サーバー側でのバリデーションも大切です。Thymeleafのテンプレートで安全に扱っていても、Controllerで受け取る値が不正であれば、結局はアプリケーション全体に影響が出ることがあります。そのため、Springの@Validアノテーションや入力チェックを組み合わせて、データの信頼性を担保するのが基本です。
さらに、JavaScriptでデータを扱う際には、HTMLに直接埋め込むのではなく、オブジェクト形式でまとめると安全です。たとえば、ユーザー情報を一つずつ出力するのではなく、まとめてオブジェクトとして扱うことで、余計な出力が減り、構造もわかりやすくなります。
<script th:inline="javascript">
window.safeUser = {
name: [[${userName}]],
age: [[${userAge}]]
};
</script>
このように、Thymeleafで値をJavaScriptに渡す際は、「エスケープ+構造化」を意識すると安全です。これがスクリプトインジェクション対策の第一歩です。
7. 実際のプロジェクトで使える設計例(Controller → Thymeleaf → JSファイル)
ここでは、実際のSpringプロジェクトで使える「Thymeleafと外部JavaScript連携の設計例」を紹介します。初心者でも理解しやすいように、Controllerから画面、そして外部JavaScriptまでの流れを順番に追ってみましょう。
まずはControllerです。ユーザーのステータス情報をHTMLに渡す簡単な例を考えます。
@Controller
public class StatusController {
@GetMapping("/status")
public String status(Model model) {
model.addAttribute("userName", "鈴木一郎");
model.addAttribute("userStatus", "ログイン中");
return "status";
}
}
次に、Thymeleafテンプレート(status.html)側でこの値を受け取り、JavaScriptで使えるようにします。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>ユーザーステータス</title>
</head>
<body>
<h2 th:text="'こんにちは、' + ${userName} + 'さん!'"></h2>
<p th:text="'現在の状態:' + ${userStatus}"></p>
<script th:inline="javascript">
window.userInfo = {
name: [[${userName}]],
status: [[${userStatus}]]
};
</script>
<script th:src="@{/js/status.js}"></script>
</body>
</html>
最後に、外部JavaScriptファイル(status.js)を作成します。このファイルはsrc/main/resources/static/js/に配置します。
// static/js/status.js
document.addEventListener("DOMContentLoaded", () => {
console.log("ユーザー名:", window.userInfo.name);
console.log("ステータス:", window.userInfo.status);
});
このように、Controller → Thymeleaf → JavaScriptという流れで値を受け渡す設計を行うと、アプリ全体の構造が明確になり、再利用性や保守性も高まります。特に外部ファイルを使うことで、画面デザインとロジックを分離できる点が大きなメリットです。
また、今後データを非同期で更新したい場合も、この構成がそのまま活用できます。例えば、fetchやAjax通信でサーバーに再リクエストを送り、取得したデータを既存のスクリプトで処理する形に拡張できるのです。
8. 外部ファイル連携を使って動的処理を実現する流れまとめ
ここまで学んだ内容を整理して、Thymeleafと外部JavaScriptを連携させて「動的処理」を行う全体の流れをまとめてみましょう。
まず、ControllerでJavaのオブジェクトや文字列をモデルに格納します。次に、Thymeleafテンプレートでその値をJavaScript変数に埋め込みます。そして最後に、外部JSファイルでその変数を参照して動的な画面操作を行う、というステップ構成になります。
- Controllerでデータを設定(Modelに格納)
- ThymeleafでHTMLレンダリング+JavaScript変数へ値を埋め込み
- 外部JavaScriptで動的処理を実行(表示更新・イベント操作など)
この流れを一度理解すれば、実際の開発でよくあるケースにも応用できます。たとえば、ログイン後のユーザー情報表示や、商品一覧の動的フィルタリングなどです。
さらに、Thymeleafの強みは、サーバーサイドでのテンプレートレンダリングとJavaScript側での動的処理を自然に橋渡しできる点です。つまり、サーバーのデータとフロントの動きをシームレスにつなぐことができるのです。
また、外部ファイル連携を活用することで、プロジェクトのメンテナンス性も格段に上がります。すべてのスクリプトをHTML内に書くのではなく、ファイル単位で管理することで、修正箇所を簡単に特定できるようになります。これはチーム開発では特に重要なポイントです。
最後にもう一度まとめると、ThymeleafとJavaScriptの連携を行う際は、次の3点を意識しましょう。
- 安全な値渡し([[ ]]でエスケープ)
- Controller→Template→JSの明確なデータフロー
- 外部ファイルによる保守性と再利用性の確保
この3つを守ることで、ThymeleafとJavaScriptを使った動的な画面処理がより安全で効率的になります。初心者のうちは少し手順が多く感じるかもしれませんが、一度構造を理解すれば、どんな画面でも同じパターンで組み立てられるようになります。
今回紹介した構成は、pleiades+Gradle環境で簡単に再現できます。ぜひ、自分のSpringプロジェクトに取り入れて、ThymeleafとJavaScriptの連携を実践してみてください。