Thymeleaf でHTMLのレイアウトを共通化

f:id:ts0818:20200718183029j:plain

レイアウト英語layout、 lay-out)とは、デザイン(紙、ウェブ等)、建築設計インテリア(展示会場・展覧会場設計、ショールーム設計などを含む)、書籍雑誌新聞などの編集等々において、何をどこにどのように配置(割り付け)するかということ、また、そのような配置(割り付け)をする行為も意味する。

レイアウト - Wikipedia

なお、レイアウトという言葉を日本に初めて紹介したのは、当時『廣告界』の編集長であった室田庫造であるという(1929年)。(「近代広告の誕生 ポスターがニューメディアだった頃」(竹内幸絵、青土社、2011年)、120ページ参照)

レイアウト - Wikipedia

⇧ レイアウトって言葉が日本に来たのは、1929年っすか、昭和4年らしい。

ちなみに、Webページのレイアウトを行うは、Webデザイナーですが、

ウェブデザイナー (web designer) とは、ウェブ(World Wide Web)に関係するデザイナーである。

ウェブデザイナー - Wikipedia

本来、「デザイン」という語は「設計」という語と同一の語であり、ウェブに関係する設計をする者、という意味でも本来の語義的には全く同じであるが、英語圏における英単語の design も含め、情報アーキテクチャの構築などといった「設計」という意味と、ウェブの場合ならばスタイルシートの設計などのような「見た目」をいじることという意味の「デザイン」とを、全く乖離したものと理解して、「デザイン設計」という本来の意味から考えればまったく意味がわからない語も堂々と通用している、といった現状のため、「ウェブデザイナー」という語も、見た目の設計をする者、といったような意味で使われているようである。

ウェブデザイナー - Wikipedia

⇧ 結構、情報が混乱してるようね...


By the way、 

takehora.hatenadiary.jp

パフォーマンスチューニングの際に、ボトルネックの診断や判断を、自動診断ツールに頼っている限り、ボトルネックの診断や解決の能力は決して磨かれる事はありません。そのツールの使い方が上手になるだけです。それを技術力の向上とは言いません。

Webパフォーマンスの振り返り 2019 - Webパフォーマンスについて

⇧ ド正論で同感なんですが、如何せん、昨今の開発の現場ってフレームワークを使う場合が圧倒的に多数で、そういった意味ではフレームワークというツールに依存せざるを得ない気がしますかね。

かと言って、現状の現場では、フルスクラッチで開発するような機会に恵まれることは稀であるし、ドキュメントも中途半端なフレームワークを使わざる得ないですし、ブラックボックス化してる部分のあるフレームワークの技術を基本的なことに結び付けるのが難しいこともあり、技術力の向上がスムーズにいかない秩序の無い現代にドロップキックという気がします。

 

間違ったやり方を試行錯誤したところで、間違った方法が上手くなるだけ、って言うのは確かに仰る通りだとは思いますが、正しい知識が無い中で、開発の納期がある以上、とにかく動くものを作らざるを得ないっていう、のっぴきならない事態に常にさらされ続ける中、トライアンドエラーを繰り返すしかないわけです。

で、結果、

news.mynavi.jp

Stack Overflowは以前、同社のQ&Aサイトに掲載されているソースコードはセキュリティ上、好ましくないものが少なくないという研究結果を伝えている。今回、前回の発表をベースとしつつ、上位8つの脆弱性がまとめられている。

Stack Overflow、ソースコードから発見した脆弱性トップ8を発表 | マイナビニュース

脆弱性を持つかもしれないソースコードが入り込む余地を与えてしまう機会が訪れてしまうわけですと。

善意が生む負の連鎖ってやつですかね、まぁ、溺れる者は藁をもつかむ、ってあるように、差し迫った状況に絶えず身を置く開発者にとっては、とにかくシステムが動いてくれないことには前に進めないわけです。

何で脆弱性が発生したんだ、って言う前に、そういうことが起きないように後進が正しい方法を身に着けられるような情報を広めていくのが良い気がしますが、そのためには優れた人の方法を真似るのが一番で、ソースコードなんかは写経するのが良いと言われますね。

ただ、ネットの情報って端折った情報や動かないソースコードが多いんですよね、つまり写経に適した情報が見つかりにくい。

なので、優れた技術者の元でOJTなんかを受けられればそれに越したことはないのですが、まぁ、そんな僥倖に巡り合う人は限られてますと。

それ以外は、泥沼でもがくしかないですと。

 

と言うわけで、モチベーションだだ下がりですが、SpringBootが推奨しているテンプレートエンジンのThymeleafについて、レッツトライ~。

 

そもHTMLのレイアウト構成って?

まずは、HTMLって何ぞ?

HyperText Markup Languageハイパーテキスト マークアップ ランゲージ)は、ハイパーテキストを記述するためのマークアップ言語の1つ。略してHTML(エイチティーエムエル)と呼ばれることが多い。SGMLを元に開発された。

HyperText Markup Language - Wikipedia

⇧ ということらしく、「ハイパーテキスト」はと言うと、

ハイパーテキスト (hypertext) とは、複数の文書テキスト)を相互に関連付け、結び付ける仕組みである。「テキストを超える」という意味から"hyper-"(~を超えた) "text"(文書)と名付けられた。テキスト間を結びつける参照のことをハイパーリンクと言う。

ハイパーテキスト - Wikipedia

⇧ ページ遷移とかできるってことね。

紙媒体の文書にしろ、Web上で見れるサイトにしろ、複数のページがあるものですと。仮に10000ページあったとして、すぐにページを参照できるってのは画期的ですよね?

ハイパーテキストは、それを実現する仕組みで、ハイパーリンクでどこを参照するのかを指定できますと。

HTMLの元になってる「SGML(Standard Generalized Markup Language)」ってのは、

Standard Generalized Markup Language(スタンダード ジェネラライズド マークアップ ランゲージ、略:SGML)は、マニュアルなどの文書のためのマークアップ言語である。SGMLXMLの対応(比較)については、ジェームズ・クラークによる「Comparison of SGML and XML」というタイトルの、1997年12月15日に議論のためにまとめられた(何らかの公式のものではない)ノートがあり、それによればSGML (ISO 8879) とXMLの関係はスーパーセットともサブセットとも結論付けられてはいない。

Standard Generalized Markup Language - Wikipedia

⇧ マニュアルなどの文書の用途だったと。

XML 1.0のAppendix CではNon-Normative(参考)として、XMLSGMLのサブセットとなるべく設計され(designed to be)、全てのXML文書は同時にSGMLにもconforming(準拠)でもあるべき(should)と書かれており、前述のノートを参照せよとされている。国際標準は ISO 8879:1986 であり、対応するJISとして JIS X 4151:1992 が存在する。

Standard Generalized Markup Language - Wikipedia

⇧ 理想と現実のギャップ?

脱線しましたが、HTMLに戻って、

World Wide Web (WWW)において、ウェブページ(1990年代後半頃からはコンテンツという語も利用されている。「中身」という意味の語であり、大層な意味は無い)を表現するために用いられる。

HyperText Markup Language - Wikipedia

⇧からの~、

ハイパーリンクや画像等のマルチメディアを埋め込むハイパーテキストとしての機能、見出し段落といったドキュメントの抽象構造、フォントや文字色の指定などの見た目の指定、などといった機能がある。

HyperText Markup Language - Wikipedia

⇧からの~、

⇧まさかの、W3C勧告に至った仕様が無いんですって...

HTMLって仕様が定まってなかったんだ...衝撃なんですけど。「仕様がない」ってことにならないように、「仕様」はちゃんとして欲しいところですね。

とりあえず、

www.w3schools.com

⇧ 上記サイト様の図のような構成がHTMLのbody部分のレイアウトの基本形になるんですかね?

このへんは、プロジェクトによって変わってくるとは思いますが、HTMLのbody部分のベーシックな構成としては、

  • header
  • nav
  • contents
    • section
    • article
    • aside
  • footer

みたいな感じで、大きく分けると4つのブロックになるイメージですかね。

デザインに重きをおくと、だいぶ趣が異なる構成も出てくるとは思いますが、デザイン寄りだと、

muuuuu.org

⇧ 上記サイト様が、いろんなサイトを集めてくれています。

Chromeとかでサイトを表示して右クリックで「検証(I)」もしくは、「ページのソースを表示(V)」でHTMLのレイアウトが確認できます。

f:id:ts0818:20200715223834p:plain

f:id:ts0818:20200715224123p:plain

⇧ 「検証(I)」の場合は「Elements」でHTMLの構成が確認できます。

うん、ベーシックな構成じゃない...

まぁ、HTMLの構成はブラウザで確認し易いのがありがたいですが。

 

ThymeleafのDialectでレイアウトの共通化が実現できるらしい

Thymeleafって?

www.thymeleaf.org

Thymeleafは、ウェブとスタンドアローンどちらの環境でも利用できる、モダンなサーバーサイドJavaテンプレートエンジンです。HTML、XMLJavaScriptCSS、さらにプレーンテキストも処理することができます。

Tutorial: Using Thymeleaf (ja)

⇧ ってな感じで、Javaのテンプレートエンジンですと。

テンプレートエンジンって?

テンプレートエンジンテンプレートと呼ばれる雛形と、あるデータモデルで表現される入力データを合成し、成果ドキュメントを出力するソフトウェアまたはソフトウェアコンポーネントである。

テンプレートエンジン - Wikipedia

⇧ サーバーサイドからのデータなんかを取り込んでページを生成できるってことですかね。

ちなみに、テンプレートエンジンを使わなくても、JavaScriptなんかと連携してRESTでサーバーサイドのデータを取り込むという方法もありますね。

 

そんなJavaのテンプレートエンジンであるThymeleafの標準の機能でも、ある程度のところまではできるらしいんですが、コンテンツ部分だけ可変にしたいって場合は、Layout Dialect ってものを依存関係に追加する必要があるらしい。

www.saka-en.com

qiita.com

⇧ 上記サイト様のようなことをすれば、例えば10000ページとかあるようなサイトの場合に、コンテンツ部分だけを考えればよくなりますと、だとしても、10000ページもコンテンツを考えないといけない場合は地獄であることに変わりはないけど...。

なので、ある程度、ページのフォーマットが決まってる場合に有効と言えますかね。ページ毎にフォーマットがバラバラだとあんまり有効ではないかな。

 

実際にLayout Dialect を導入してみる

Eclipseを起動して、「ファイル(F)」>「その他(O)...」を選択。 

f:id:ts0818:20200718125855p:plain

「Spring Boot」>「Spring スターター・プロジェクト」を選択で、「次へ(N)>」。

f:id:ts0818:20200718130009p:plain

このあたりは各々の使い方に合わせて設定で。

「名前」「型:」「パッケージング:」「Java バージョン:」「言語:」「説明」あたりを設定すれば良いのではないかと。設定が済んだら「次へ(N)>」。

f:id:ts0818:20200718130301p:plain

依存関係は

  • 開発ツール
    • Spring Boot DevTools
  • テンプレート・エンジン
    • Thymeleaf
  • Web
    • Spring Web

を一旦追加しておきます。(「Layout Dialect」は後ほど追加します。)

「完了(F)」で。

f:id:ts0818:20200718130844p:plain

プロジェクトができるので、その中の「pom.xml」を開きます。

f:id:ts0818:20200718131122p:plain

Maven Repository に「Layout Dialect」のライブラリがあるので、

mvnrepository.com

⇧ 上記サイトにアクセスして、

⇩ 適当なバージョンを選択。今回は、「2.4.1」を選択しました。

f:id:ts0818:20200718131700p:plain

自分は、ビルドツールに「Maven」を使っているので、「Maven」タブに表示されている「依存関係」追加のためのコードをコピーします。

f:id:ts0818:20200718131829p:plain

で、Eclipseで開いていた「pom.xml」に「依存関係」として追加します。ただ、「<version>」タグは、警告が出るので削ってます。

あと、「JavaScript」や「CSS」のライブラリを「Jar」として読み込むこともしてみたいと思います。(大規模開発の場合、フロントエンドとサーバーサイドで分かれることが多いと思うから、フロントエンド部分のリソースは、サーバーサイド側であるビルドツールで管理しないとは思うけど。)

www.webjars.org

⇧ 上記サイトにアクセスし、

f:id:ts0818:20200718134336p:plain

自分の使ってるビルドツールのタブを選択して、自分の利用したいライブラリの「依存関係」追加のためのコードをコピペして、Eclipseで開いていた「pom.xml」に「依存関係」として追加します。

 

追加する個所は、「<depndencies>」タグ内ならどこでもOKかと。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>SpringBoot-Thymeleaf-LayoutDialect</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringBoot-Thymeleaf-LayoutDialect</name>
	<description>Thymeleaf Layout Dialect for Spring Boot</description>

	<properties>
		<java.version>11</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<!-- 追加↓ここから -->
		<!-- https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect -->
		<dependency>
		    <groupId>nz.net.ultraq.thymeleaf</groupId>
		    <artifactId>thymeleaf-layout-dialect</artifactId>
		</dependency>
		<dependency>
		    <groupId>org.webjars</groupId>
		    <artifactId>jquery</artifactId>
		    <version>3.5.1</version>
		</dependency>
		<dependency>
		    <groupId>org.webjars</groupId>
		    <artifactId>bootstrap</artifactId>
		    <version>4.5.0</version>
		</dependency>
		<!-- 追加↑ここまで -->
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

追加できたら、以下のように、「/プロジェクト名/src/main/resources/templates」配下に、HTMLファイルを配置していきます。

f:id:ts0818:20200718185501p:plain

あとは、ホットデプロイのために「application.properties」にThymeleafのキャッシュを無効にする設定を記載しておきます。(本番環境では有効にするとは思いますが、開発環境では、効率化のために無効にします。)

f:id:ts0818:20200718185542p:plain

あと、「/プロジェクト名/src/main/java」にコントローラーとなるクラスを作成しておきます。

f:id:ts0818:20200718185658p:plain

 

最終的なソースコード一式はGitHubに上げましたので、宜しければご参照ください。

github.com

 

で、「@SpringBootApplication」アノテーションの付与されたクラスにmainクラスがあるので、そのクラスを選択した状態で右クリックし、「実行(R)」>「Spring Boot アプリケーション」をクリック。

f:id:ts0818:20200718190917p:plain

ブラウザで、「http://localhost:8080/」にアクセスすると、

f:id:ts0818:20200718163007p:plain

「/プロジェクト名/src/main/resources/templates/index.html」が表示されました。

「/プロジェクト名/src/main/resources/templates/commons」に配置したHTMLファイルの内容も読み込めています。

http://localhost:8080/welcome」にアクセスすると、

f:id:ts0818:20200718163048p:plain
「/プロジェクト名/main/resources/templates/welcome.html」が表示されています。

「/プロジェクト名/src/main/resources/templates/commons」に配置したHTMLファイルの内容も読み込めています。

 

実際に使う場合は、サーバーサイド側のデータとかをコントローラークラス経由でHTMLとやり取りすることになる感じになるかとは思いますが、今回はあくまで、HTMLの部分に焦点を当てたので、データ部分は割愛してます。

気になるのは、実際の現場でThymeleafがどのぐらい使われてるかですかね、モヤモヤが残りますな。

今回はこのへんで。