Tailwind CSS & daisyUI & Alpine.js 整合配置

Tailwind CSS & daisyUI & Alpine.js 整合配置

將 Tailwind CSS, DaisyUI 和 Alpine.js 整合到 Hugo 專案中,能為您的網站開發帶來多方面的優勢,讓您更輕鬆地打造出現代化、互動性強且美觀的網站。

Tailwind CSS 的優勢

  • 高度客製化: Tailwind CSS 提供了大量的 utility classes,讓您可以自由組合出所需的樣式,而不需要寫大量的 CSS。
  • 快速開發: 透過 Tailwind CSS,您可以快速建立出原型,並在開發過程中不斷迭代。
  • 一致性: Tailwind CSS 強調一致性,讓您的網站風格更加統一。

DaisyUI 的優勢

  • 開箱即用的元件: DaisyUI 提供了一系列預先設計好的元件,如按鈕、卡片、模態框等,讓您可以快速搭建複雜的 UI。
  • 響應式設計: DaisyUI 的元件都是響應式的,能夠適應不同尺寸的螢幕。
  • 主題客製化: DaisyUI 提供了多種主題,您可以根據自己的需求進行客製化。

Alpine.js 的優勢

  • 輕量級: Alpine.js 是一個輕量級的 JavaScript 框架,專注於為 HTML 元素添加行為。
  • 易於學習: Alpine.js 的語法簡單易懂,即使沒有深入的 JavaScript 知識,也能快速上手。
  • 高效能: Alpine.js 的性能優異,不會影響網站的載入速度。

整合後的優勢

  • 快速開發: 結合 Tailwind CSS, DaisyUI 和 Alpine.js,您可以快速搭建出功能豐富且美觀的網站。
  • 提升開發效率: 這些工具可以減少您編寫 CSS 和 JavaScript 的時間,讓您專注於網站的內容和邏輯。
  • 提升使用者體驗: 透過互動性的元素和美觀的設計,您可以提升用戶的體驗。

整合步驟

1. 安裝套件

首先,在您的專案根目錄下執行以下指令,安裝所需的套件:

npm install -D \
  @tailwindcss/aspect-ratio \
  @tailwindcss/typography \
  @alpinejs/intersect \
  @alpinejs/persist \
  alpinejs \
  daisyui \
  tailwindcss \
  theme-change
// 或使用 yarn 
yarn add -D \
  @tailwindcss/aspect-ratio \
  @tailwindcss/typography \
  @alpinejs/intersect \
  @alpinejs/persist \
  alpinejs \
  daisyui \
  tailwindcss \
  theme-change

詳細說明:

  • yarn add: 這是 Yarn 的安裝指令,用於將指定的套件添加到專案中。
  • -dev: 這個參數表示將這些套件安裝為開發依賴 (devDependencies)。開發依賴只在開發環境中使用,不會被包含在最終的生產環境中。

安裝的套件:

  • @tailwindcss/aspect-ratio: Tailwind CSS 的外掛程式,用於處理元素的寬高比。
  • @tailwindcss/typography: Tailwind CSS 的外掛程式,提供預定義的排版樣式,如標題、段落、列表等。
  • alpinejs: 一個輕量級的 JavaScript 框架,用於為 HTML 元素添加交互性。
  • daisyui: 基於 Tailwind CSS 的 UI 元件庫,提供了一系列預製的 UI 元件,如按鈕、卡片、模態框等。
  • tailwindcss: Tailwind CSS 框架的核心套件。
  • @alpinejs/intersect: Alpine.js 的外掛程式,用於監聽元素是否進入視窗可見區域。
  • @alpinejs/persist: Alpine.js 的外掛程式,用於持久化 Alpine.js 的狀態。

2. 定義 Tailwind CSS

  • 在根目錄下新增 tailwind.config.js ,內容如下:

    /** @type {import('tailwindcss').Config} */
    
    module.exports = {
      mode: "jit",
      content: [
        "./content/**/*.{html,js,md}",
        "./data/**/*.json",
        "./themes/my-theme/content/**/*.{html,js,md}", // 確保包含主題的 content
        "./themes/my-theme/layouts/**/*.html", // 確保包含主題的 layouts
        "./themes/my-theme/assets/js/**/*.js", // 確保包含主題的 JS
      ],
      safelist: [],
      darkMode: "class",
      important: true,
      theme: {
        extend: {},
      },
      daisyui: {
        themes: ["light", "dark", "cupcake"],
      },
      plugins: [
        require("@tailwindcss/aspect-ratio"),
        require("@tailwindcss/typography"),
        require("daisyui"),
      ],
    };
    
  • 修改 themes/my-theme/assets/css/app.css ,內容如下:

    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
  • 在根目錄底下新增 postcss.config.js,內容如下:

    let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js';
    const tailwind = require('tailwindcss')(tailwindConfig);
    const autoprefixer = require('autoprefixer');
    const postcssPresetEnv = require('postcss-preset-env');
    
    module.exports = {
    	// eslint-disable-next-line no-process-env
    	plugins: [
            tailwind,
            postcssPresetEnv(), // Add postcss-preset-env here
            ...(process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : []) 
        ],
    };
    

3. 引入 Alpine.js

  • 修改 themes/my-theme/assets/js/app.js,內容如下:

    import '../css/app.css';
    
    // 主題切換
    import './theme.js';
    
    import Alpine from 'alpinejs';
    import intersect from '@alpinejs/intersect';
    import persist from '@alpinejs/persist';
    
    // Set up and start Alpine.
    (function() {
        // Register AlpineJS plugins.
        Alpine.plugin(intersect);
        Alpine.plugin(persist);
    
        // Start Alpine.
        Alpine.start();
    })();
    
  • 新增 themes/my-theme/assets/js/theme.js,內容如下:

    import 'theme-change';
    const checkbox = document.getElementById('theme-toggle');
    const themes = checkbox.dataset.setThemeTarget.split(','); // 取得主題名稱
    
    // 初始設定
    const storedTheme = localStorage.getItem('theme');
    if (storedTheme) {
      document.documentElement.setAttribute('data-theme', storedTheme);
      checkbox.checked = storedTheme === themes[0]; // 根據儲存的主題設定 checkbox 狀態
    } else {
        document.documentElement.setAttribute('data-theme', themes[1]);
        checkbox.checked = false;
    }
    
    checkbox.addEventListener('change', () => {
      const theme = checkbox.checked ? themes[0] : themes[1];
      document.documentElement.setAttribute('data-theme', theme);
      localStorage.setItem('theme', theme); // 儲存主題到 localStorage
    });
    

4. 主題版型配置

  • 使用 DaisyUI 的元件: 參照 DaisyUI 的官方文件,在您的模板中使用其提供的各種元件。

  • 使用 Alpine.js 的指令: 在您的 HTML 元素上使用 Alpine.js 的指令,例如 x-datax-showx-on 等,來實現互動功能。

    修改 themes/my-theme/layouts/_default/baseof.html

    <!-- 找到以下 -->
    <html lang="{{ site.Language.LanguageCode }}" dir="{{ or site.Language.LanguageDirection `ltr` }}">
    
    <!-- 加入 data-theme="light" ,如下 -->
    <html data-theme="light" lang="{{ site.Language.LanguageCode }}" dir="{{ or site.Language.LanguageDirection `ltr` }}"> 
    
    <!-- 找到以下 -->
    <body>
    
    <!-- 加入 Tailwind 的 class ,如下 -->
    <body class="{{ if .Params.white_bg }}bg-white dark:bg-gray-900{{ else }}bg-gray-50 dark:bg-gray-800{{ end }}">
    

    修改 themes/my-theme/content/_index.html ,內容如下:

    ---
    title: Hugo + Alpine.js + Tailwind CSS + daisyUI
    description: Starter
    layout: main
    navbar: default
    date: 2023-01-01T08:00:00-07:00
    draft: false
    ---
    
    <div class="mockup-browser border bg-base-300">
      <div class="mockup-browser-toolbar">
        <div class="input">
          <a href="https://www.makiot.com" target="_blank"
            >https://www.makiot.com</a
          >
        </div>
      </div>
      <div class="flex justify-center bg-base-200 px-4 py-16">
        <div class="hero min-h-screen bg-base-200">
          <div class="hero-content flex-col lg:flex-row">
            <img
              src="https://img.daisyui.com/images/daisyui-logo/daisyui-logomark.svg"
              class="max-w-sm rounded-lg"
            />
            <div>
              <h1 class="text-5xl font-bold">daisyUI + Alpine.js</h1>
              <p class="py-6">
                如果你看到網頁內容有:瀏覽器的外觀;有主題切換;點擊計數按鈕,即是正確的配置好了
              </p>
              <div class="flex items-center space-x-4">
                <button class="btn btn-primary">切換主題:</button>
                <label class="swap swap-rotate">
                  <input type="checkbox" id="theme-toggle" data-set-theme-target="light,dark" />
                  <svg
                    class="swap-on h-10 w-10 fill-current"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                  >
                    <path
                      d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"
                    />
                  </svg>
                  <svg
                    class="swap-off h-10 w-10 fill-current"
                    xmlns="http://www.w3.org/2000/svg"
                    viewBox="0 0 24 24"
                  >
                    <path
                      d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"
                    />
                  </svg>
                </label>
                <div class="flex items-center space-x-2" x-data="{ count: 0 }">
                  <button x-on:click="count++" class="btn btn-primary">點擊計數+1:</button>
                  <span x-text="count"></span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    

    在 themes/my-theme/layouts/_default/ 底下新增 main.html ,內容如下:

    {{ define "main" }}
      {{ .Content }}
    {{ end }}
    

整合配置重點

  • package.json 配置: scripts 中的 build:css 這段會將主題內的css 打包並輸出到 static 目錄底下

    {
     ...
       "scripts": {
        ...
        "build:css": "npx tailwindcss -i ./themes/my-theme/assets/css/app.css -o ./static/app.css --minify"
      },
      ...
      }
    
  • tailwind.config.js: 用以配置外觀樣式,重點內容如下:

    module.exports = {
      mode: "jit",
      content: [
        "./content/**/*.{html,js,md}",
        "./data/**/*.json",
        "./themes/twda/content/**/*.{html,js,md}", // 確保包含主題的 content
        "./themes/twda/layouts/**/*.html", // 確保包含主題的 layouts
        "./themes/twda/assets/js/**/*.js", // 確保包含主題的 JS
      ],
      ...
      daisyui: {
        themes: ["light", "dark", "fantasy"], //指定要嵌入的主題
      },
      plugins: [
        require("@tailwindcss/aspect-ratio"), // 使能自適應使用者螢幕的尺寸
        require("@tailwindcss/typography"), //使 CSS 樣式能支援 markdown 格式
        require("daisyui"), //嵌入 daisyui
      ],
    };
    
  • webpack.config.js : 打包 app.js ,將複雜的 javascript 封裝成一個檔案;匯入打包 js 及 css 的外掛。重點配置如下:

    module.exports = {
      entry: {
        app: path.resolve(__dirname, 'themes/my-theme/assets/js/app.js') //注意:需指向你正在使用的主題 theme
      },
      output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'static/'),
      },
      ...
     }
    

進一步優化

  • Tailwind CSS 配置: 主要根據 DaisyUI 快速設計版型,若不足之處再引用 Tailwind CSS。
  • Alpine.js : Hugo 不適合與 React, Vue, Angular 等前端語言整合,至目前為止 alpine.js 是最適合 Hugo 體質的 js lib (也不建議使用 jQuery),利用它可以整合第三方服務或自建 API 服務,用以擴展網站功能。
  • 性能優化: 對於大型專案,可以考慮使用 PurgeCSS 來移除未使用的 CSS,以提高網站性能。