Thymeleaf で HTML を共通部品化してデザイン統一と開発効率の向上を図った

Spring Boot + Thymeleaf な環境において、複数人でフロントエンド開発をすることがあり、
同じ構造とデザインがよく現れる場合において、こんな課題があってこう解決したっていうメモです。
(誰かに引き継ぐとしても共通部品化はアリかも)

環境

Spring Boot: 1.3.2 RELEASE
Thymeleaf: 2.14 RELEASE

Thymeleaf とは

テンプレートエンジンの 1 つであり、Java 環境での使用が推奨されています。
私が気に入っているのは、HTML の中に Thymeleaf 独自の構文を埋め込んで使うことができる点です。
まず ネイティブな HTML を書いて、大まかに構造やデザインを決め、そのコードをあまり破壊せずに
完成させていくことができます。
(私は他のテンプレートエンジンを使ったことがなく……実は世の中そういうものなのかもしれませんが)
Spring Boot と組み合わせると、いろいろできるよ(雑ですが)と言われています。
公式サイト:http://www.thymeleaf.org/

私がいた現場での課題

実はこれ 2 年弱前のことで、最近フロントエンドに戻って思い出したので書いてます。
当時、開発の真っただ中で、以下の課題を抱えていました。

  • 複数人が画面テンプレートを実装しており、各々が実装した構造やデザインにバラつきがあった。
    (コーディング規約はあったが、残念ながら全員が守っているわけではなかったので、規約を充実させるのは現実的ではないとした(この判断がただしかったのか今でも疑問。後から充実させたが、最初にするべきだったのでは……))
  • サーバサイド開発タスクが増えるにつれ、画面テンプレートの実装には少人数での担当(効率)が求められた。
    (最終的には私一人で weekly 数十個の画面テンプレートをつくらなくてはならなかった)

Thymeleaf でつくる共通部品

結論から行くと、こんな感じでつくります(Thymeleaf の文法については省略します)。

呼出側
<!-- form.html 内にある text-form という部品を呼び出す。
     引数として、templateId, label, required を渡す。
     templateId には "accountName" という文字列を渡す。
     label にはメッセージリソース内で msg.account.name に定義されている文字列を渡す。
     required には false を渡す -->
<div th:replace="form :: text-form(
    templateId = 'accountName',
    label      = #{msg.account.name},
    required   = false)">
</div>
共通部品
<!-- text-form という名前の部品である。
     引数として、templateId, label, required を受け取る。 -->
<div th:fragment="text-form(templateId, label, required)">
    <label th:for="${templateId}" th:text="${label}"></label>
    <div>
        <input type="text" th:id="${templateId}" th:name="${templateId}" th:field="*{__${templateId}__}"
               th:required="${required}? required"/>
    </div>
</div>

実際は CSS クラスの適用やら Javascript の呼び出しやらがあり、複雑になりますが、共通部品を定義しておけば、
必要な部品に必要なパラメータを渡して呼び出すだけで、デザインの統一が取れた構造を効率よく作っていけます。

共通部品化をした後の課題

デザインの統一が取れたうえに効率的に画面テンプレートを開発でき、無事に予定通りリリースすることができました。
しかし、開発が進んでくると、以下の課題がでてきました。

  • 多少関わらずデザイン差分単位で共通部品を作ったため、共通部品が大量に生まれてしまい、適した共通部品を探すコストが大きくなった。
    → これは例えば、引数が変わらない範囲で、共通部品内に switch 構文を書くなどすれば部品数を削減でき改善できると思います。
    → 本質的には設計の問題なのかもしれません。
  • 共通部品にする単位の設計に充分に時間を割いておらず、最適とはいえない単位で作られた共通部品が多々ある。
    → 上記のコード例ではフォーム単位ですが、これが最適なのか? という検証はプロダクトごとにあるはず。
    → layout-dialect 機能( http://www.ultraq.net.nz/thymeleaf/layout )を駆使するのは一手ですね。

個人的に考えていること

  • そもそも自動生成の道があったのではないかということ
    → 当時は考えもつかなかったが……。今は修正がメインですが、当時は大いに価値があったはず。
  • Thymeleaf 3.x にアップデートすると更に効率的な共通部品化の道があるのではないかということ
    → 共通部品化に使えそうな新機能がいくつか見受けられた。後方互換性があるので、あまり怖くはないはず
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.