【Spring Boot】Tailwind CSS 導入方法

&emsp;

**Spring Bootアプリ開発で、Tailwind CSSの記法を反映させるまでの導入手順**は、次の順番で説明します。

1. 開発環境
1. 導入の準備
1. 具体的な導入手順《本編》
1. Tailwind CSSが反映されないときの対処法

「開発環境」では、本記事で解説する内容が正しく挙動したことを実際に視認できた条件・環境を整理しました。「導入の準備」では、本格的な導入の前までに実装しておきたいことを整理しました。「具体的な導入手順《本編》」では、実際にSpring Boot へ Tailewind CSS を適用させる方法を整理しました。「Tailwind CSSが反映されないときの対処法」では、ボク自身が初めてSpring Boot アプリ開発で Tailewind CSS を組み込んだ際、困った点とその解決法をまとめました。

&emsp;

ムダな前置きは省いて、早速解説しますね :dash:
&emsp;
&emsp;

# 開発環境

| Category        | Value,Version                 |
| :-------------: | :---------------------------: |
| OS              | MacOS Sonoma 14.3.1           |
| Project	      | Gradle Groovy                 |
| Language        | Java 17                       |
| Framework       | Spring Boot 3.1.9             |
| Group           | com.project                   |
| Artifact        | sprigboottailwind             |
| Name            | SprigBootTailwind             |
| Package name    | com.project.sprigboottailwind |
| Packaging       |  Jar                          |
| Dependencies    | Spring Web, Thymeleaf         |
| Editor          | IntelliJ IDEA CE              |

:::note warn 
ここから先は「↑の内容に沿って [spring initializr](https://start.spring.io/) で作成したプロジェクトを、IntelliJで開いている」という状況を想定／前提として、解説を進めます。
:::
&emsp;
&emsp;

# 導入の準備
&emsp;

導入の準備では「**Spring Bootアプリで、トップページ：`index.html` を表示する**」をゴールに実装していきます。
&emsp;

まず、`src/main/resources/templates/` 内に `index.html` を作成します。

そして、`<body>` 内をカスタマイズします。
```html:index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>Welcome!</h1>
        <p>Lorem Ipsum</p>
    </body>
</html>
```
&emsp;

次に、`src/main/java/com.project.sprigboottailwind/`へ`RequestCntroller`（任意の名前）というコントローラー用のJavaクラスを作成します。

そして、「`index.html` ＝ トップページを表示させてください 🥺 」というリクエストに対応する処理を、次のように記述します。
```java:RequestCntroller.java

package com.project.sprigboottailwind;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class RequestController {
    @GetMapping /* ("/") はアリ／ナシどっちでもOK */
    public String index(){
        return "index";
    }   
}

```
&emsp;

ここで、一度アプリを実行して `localhost:8080` へアクセスし、トップページが正しく表示されるかどうかを確認しましょう。

正しく表示されていることを確認できたら、アプリの実行を停止します。
&emsp;

これで、導入の準備「**Spring Bootアプリでトップページ：`index.html` を表示する**」は完了です :tada:
&emsp;
&emsp;

# 具体的な導入手順《本編》
&emsp;

ここでは、本編「Spring BootアプリへTailwind CSSを反映させるまでの具体的な方法」を、次の3つに分けて解説します。

1. Tailwind CSS のインストール・・・メイン作業：コマンド操作
1. プロジェクトへの Tailwind 適用・・・メイン作業：ファイル追記／追加
1. HTML への Tailwind 反映・・・メイン作業： HTML編集
&emsp;

各ステップの詳細な情報は、実際のコードを見せながら解説しますね :relaxed:
&emsp;
&emsp;

## STEP①：Tailwind CSS のインストール
&emsp;

まず、`package.json` を追加します。

具体的には、ターミナルで次のコマンドを実行します。
```zsh:Terminal
(アプリのディレクトリへ移動)

 % npm init -y   # -y オプションを付ければ、単に npm init コマンドを実行したときに答えなきゃいけない ”yes問答” を全スキップできる
```
プロジェクトに次のファイル追加／編集がされれば、成功です。
 - [x] `package.json` 追加
&emsp;
 
> 「`Node.js`？ `npm` ？？ 何やそれ :innocent: 」という状態のとき、ひとまずのザックリ理解に役立った記事を紹介しておきますね。
>
> [オススメ記事：そろそろ適当に npm install するのを卒業する](https://zenn.dev/ikuraikura/articles/71b917ab11ae690e3cd7)

&emsp;

次に、プロジェクトへ　`tailwindcss` をインストールします。

具体的には、ターミナルで次のコマンドを実行します。
```zsh:Terminal
    % npm install -D tailwindcss   # npm = "node package manager"：package.jsonの管理をおこなうためのコマンド

    % npx tailwindcss init   # npx = "node package executer"：package.jsonの実行をおこなうためのコマンド
```

プロジェクトに次のファイル追加／編集がされれば、成功です。
 - [x] `package.json` > `devDependencies` に `tailwindcss:(ver)` の追記
 - [x] `package-lock.json` 追加
 - [x] `tailwind.config.js` 追加
&emsp;

> 「`devDependencies`？ 何やそれ :innocent: 」という状態のとき、ひとまずのザックリ理解に役立った記事を紹介しておきますね。
>
> [オススメ記事：勉強メモ/npmの使い方(node.js=v0.11.16, npm=2.3.0, 2015-03時点)](https://qiita.com/msakamoto_sf/items/a1ae46979a42d6948ebd)

&emsp;

これで「**STEP①：Tailwind CSS のインストール**」は完了です :tada:

&emsp;


## STEP②：Spring Boot プロジェクトへの Tailwind 適用
&emsp;

まず、Tailwind CSSがスタイルを適用すべきHTMLファイル（およびJSファイル）の場所を指定します。

具体的には、`tailwind.config.js` というTailwind CSSの設定ファイルの `content` 配列に次のパス指定を追加します。
```javascript:tailwind.config.js
module.exports = {
  content: ["./src/**/*.{html,js}"], // 追加
  theme: {
    extend: {},
  },
  plugins: [],
}
```
このパス指定は、次の意味を持ちます。

- [x] `**`：任意の数のサブディレクトリ
- [x] `*.{}(拡張子名が入る)`：指定した拡張子との一致

つまり、`content` 内のパス指定は「 `src` ディレクトリ下にあるすべてのファイルのうち、`.html (と .js)` という拡張子に一致するすべてのファイルにTailwind CSSを適用させてね :pray_tone1: 」という意味になります。

> このパス指定を正しく理解／指定しないと、Tailwind CSS が反映されません...

&emsp;

次に、`src/main/resources/static/` ディレクトリに `input.css` というファイルを新規作成します。

そして、次のように編集します。
```css:input.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```
この `@tailwind base;` は、Tailwind側が用意してくれた「リセットCSS」の役割を果たしています。

デフォルト設定の詳細／無効化については、次の公式ドキュメントを参考にしてください。
[参考：Preflight《tailwindcss公式》](https://tailwindcss.com/docs/preflight)

&emsp;

これで「**STEP②：Spring Boot プロジェクトへの Tailwind 適用**」は完了です :tada:

&emsp;

## STEP③：HTML への Tailwind 反映
&emsp;

まず、Tailwind CSSをビルドします。

具体的には、次のコマンド操作をします。
```zsh:Terminal
% npx tailwindcss -i ./src/main/resources/static/input.css -o ./src/main/resources/static/output.css --watch
```
正しく実行されると、ターミナル上に次のような表示があらわれ、初実行時には `resources/static/` ディレクトリ内に `output.css` ファイルが生成されます。
```zsh:Terminal
% npx tailwindcss -i ./src/main/resources/static/input.css -o ./src/main/resources/static/output.css --watch

Rebuilding... 

Done in 333ms.
```
このコマンド操作が必要な理由は、Spring Bootでは静的リソース、つまり `resources/static/` ディレクトリ内の `.css` や `.js` などのファイルの「コンパイル→（再）ビルド」というプロセスが、デフォルトだと自動でおこなわれないからです。

このコマンド操作を実行しておくことで、Tailwind CSS を変更する、つまり `class=""` 内をカスタマイズするごとに `output.css` ファイルが自動更新され、変更内容がHTMLに反映されます。

> まさに「CSSファイルの別途追記が要らない」というTailwind CSSの恩恵... 🥹

&emsp;

それでは、HTMLへTailwindを反映させます。

具体的には、Tailwindを反映させたいHTMLファイルの `<head>` へ、次の `<link>` タグを追加します。
```html:index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="/output.css" rel="stylesheet">   <!-- 追加 -->
    </head>
    <body>
        <h1>Welcome!</h1>
        <p>Lorem Ipsum</p>
    </body>
</html>
```

そして、Tailwind CSSの記法に則って、`class` 内をカスタマイズします。
```html:index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="/output.css" rel="stylesheet">
    </head>
    <body>
        <h1 class="text-3xl font-bold underline">Welcome!</h1>   <!-- カスタマイズ -->
        <p>Lorem Ipsum</p>
    </body>
</html>
```
カスタマイズしたら再ビルドがおこなわれていることをターミナル上で確認します。
```zsh:Terminal
% npx tailwindcss -i ./src/main/resources/static/input.css -o ./src/main/resources/static/output.css --watch

Rebuilding... 

Done in 333ms.

Rebuilding...   # 再ビルド

Done in 222ms.
```
これでアプリを実行して、Tailwind CSSが反映されていたら成功です。
[![Image from Gyazo](https://i.gyazo.com/41976dca6fffeb4f7f6c6d07eba75c94.png)](https://gyazo.com/41976dca6fffeb4f7f6c6d07eba75c94)

&emsp;

ここまででSTEP③完了、つまり「**Spring BootへのTailwind CSS導入手順**」は終了です :tada::tada::tada:
&emsp;

お疲れ様でした。
&emsp;
&emsp;

# Tailwind CSSが反映されないときの対処法
&emsp;

ここでは、「Spring BootアプリにTailwind CSSが反映されない... :cry: 」と困ったときに当てはまるかもしれない、未反映の原因とその解決策を紹介します。

* 古いキャッシュの問題
* ビルド忘れ
* Tailwind CSS へのパス指定ミス
&emsp;

各原因の具体的な解決策は、以降で提案しますね。
&emsp;
&emsp;

## 原因①：古いキャッシュの問題
&emsp;

「ブラウザのキャッシュが原因で古いCSSが適用されている」ことが原因で Tailwind CSSが反映されていない可能性があります...

そんなときは、次を試してみてください。

:::note
解決策①：**ブラウザのキャッシュをクリアする**
:::

> Google Chrome でうまく反映されないとき、ブラウザのキャッシュをクリアしたらうまくいきました :thumbsup_tone1:

&emsp;

## 原因②：ビルド忘れ
&emsp;

「（再）ビルドがおこなわれていない」ことが原因で Tailwind CSSが反映されていない可能性があります...

そんなときは、次を試してみてください。

:::note
解決策②：**CLIからビルドする**
```zsh:Terminal
% npx tailwindcss -i ./src/main/resources/static/input.css -o ./src/main/resources/static/output.css --watch
```
:::

繰り返しになりますが、Spring Bootでは静的リソース、つまり `resources/static/` ディレクトリ内の `.css` や `.js` などのファイルの「コンパイル→（再）ビルド」というプロセスが、デフォルトだと自動でおこなわれません。

したがって、↑のコマンドを打たないままTailwind CSSを編集→アプリを実行（サーバーを起動）しても、編集内容はビルドされない、つまりTailwind CSSが反映されない... となるので、注意しましょう。

&emsp;

## 原因③：Tailwind CSS へのパス指定ミス
&emsp;

「HTMLファイル上でTailwind CSS（output.css）へのパスが正しく設定されていない」ことが原因で Tailwind CSSが反映されていない可能性があります...

そんなときは、次を試してみてください。

:::note
解決策③：**相対パス `./` から絶対パス `/` に変更する**
```html:index.html
<!-- 変更前 -->
<link href="./output.css" rel="stylesheet">   <!-- 相対パス -->

↓

<!-- 変更後 -->
<link href="/output.css" rel="stylesheet">   <!-- 絶対パス -->
```
:::

なぜ、絶対パスで指定した方がいいかのというと、**静的ページだけでなく動的に生成されるページにも `output.css` を適用、つまり、Tailwind CSS 反映させるため** です。
&emsp;

たとえば、X（旧Twitter）のようなSpring Bootアプリを開発している場面を想像してください。

「フォローしてる人のポスト全体を見たい 🥺」というリクエストに応えるためには、`x/`（TOPページ）などの静的ページ、つまり、`index.html` を取得して表示させれば問題ありません。

一方、「このポストの詳細を見たい 🥺」というリクエストに応えるためには、`x/posts/{id}` など、URL構造が末尾のidで代わるような動的に生成されるページを詳細表示させる必要があります。

このような動的に生成されるページへのCSS適用に、絶対パスではなく相対パスを用いてしまうと、Tailwind CSS の反映されていないただのビューファイルがレンダリングされる可能性が高いです...（ブラウザのコンソールで確認すると、`400 Bad Request` 系のエラーが出てくるはず）

> Tailwind CSS 公式ドキュメントでは「相対パス」でのセットアップが書かれているので、公式に忠実に導入している方は、注意しましょう...（自戒）

&emsp;
&emsp;
&emsp;

プログラミング学習のアウトプット、以上になります。
ご指摘あれば、お気軽にコメントください。
&emsp;

[参考 + 感謝：Get started with Tailwind CSS](https://tailwindcss.com/docs/installation)
[参考 + 感謝：Spring Boot Thymeleaf Setup with Tailwind CSS | Step-by-Step Tutorial](https://youtu.be/rW-fTIVBYt4?si=3_3HNZ-K6lQzFOSi)