點燈坊

失くすものさえない今が強くなるチャンスよ

整合 Hugo 與 Petite-vue (ESM)

Sam Xiao's Avatar 2024-01-23

Petite-vue 特別適合後端有自己 Template Engine 的使用場景,Hugo 雖然為 SSG,但因為使用了 Go Template,事實上與後端類似,因此也適合 Petite-vue,更可還原 Composition API 風格在 Hugo 上。

Version

Hugo 0.121.2
Petite-vue 0.4.1

New Site

$ hugo new site hugo-pvue --format json
  • hugo new site : 以預設骨架建立 Hugo 站台
  • –format json : 以 JSON 格式作為 Hugo 設定檔

Install Petite-vue

$ npm install -D petite-vue
  • 使用 NPM 安裝 Petite-vue

Module Mounts

hugo.json

{
   "baseURL": "https://example.org/",
   "languageCode": "en-us",
   "title": "My New Hugo Site",
   "module": {
      "mounts": [
         {
            "source": "node_modules/petite-vue/dist/petite-vue.es.js",
            "target": "static/petite-vue.es.js"
         }
      ]
   }
}

Line 5

"module": {
  "mounts": [
    {
      "source": "node_modules/petite-vue/dist/petite-vue.es.js",
      "target": "static/js/petite-vue.es.js"
    }
 ]
}
  • node_modules 目錄下的 Petite-vue mount 到 static 目錄下,只是邏輯上的 mount,並不是 copy 到 static 目錄下
  • 因為在 static 目錄下的 JavaScript 可直接使用最為方便,因此選擇 mount 到 static 目錄下
  • 雖然在 static 目錄下看不到 Petite-vue,但最後會將 Petite-vue publish 到 public 目錄下

若要以 Composition API 方式使用 Petite-vue,則要使用 petite-vue.es.js

Layout

layouts/index.html

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    {{ $title := "Petite-vue Lab" }}
    <title>{{ $title }}</title>
  </head>
  <body>
    <div>{{ $title }}</div>
    <div>
      <button @click="onClick">+</button>
      <div>[[ states.count ]]</div>
    </div>
  </body>
</html>

<script type="module">
import { createApp, reactive } from './js/petite-vue.es.js'

let states = reactive({
    count: 0
  }
)

let onClick = () => states.count++

createApp({
  $delimiters: ['[[', ']]'],
  states,
  onClick
}).mount()
</script>

Line 6

{{ $title := "Petite-vue Lab" }}
<title>{{ $title }}</title>
  • 定義 Go template 變數
  • 顯示 Go template 變數

Line 13

<div>[[ states.count ]]</div>
  • 顯示 Petite-vue 變數

Petite-vue 使用與 Go template 不同的 delimiter

Line 18

<script type="module">
  • 使用 ESM 寫 Petite-vue

Line 19

import { createApp, reactive } from './js/petite-vue.es.js'
  • petite-vue.es.js 引用出 createApp()reactive(),這是使用 Petite-vue 最重要的兩個 function

Line 28

createApp({
  $delimiters: ['[[', ']]'],
  states,
  onClick
}).mount()
  • createApp():統整所有 state 與 method
  • mount():最後加上 mount() 綁定到 HTML

Line 29

$delimiters: ['[[', ']]'],
  • 設定 Petite-vue 的 delimiter,特別避開 Go template 使用不同的 delimiter

Line 21

let states = reactive({
    count: 0
  }
)
  • 將 state 包在 reactive()

Line 26

let onClick = () => states.count++
  • 定義 method,不必寫在 methods 下,直接以 function 即可,且不是使用 this 存取 state

Conclusion

  • 在 Hugo 似乎較流行使用 Alpine,雖然 Alpine 與 Vue 十分相似,但若想維持 Vue 的風格,在 Hugo 使用 Petite-vue 也是不錯選擇
  • 使用 Module Mount 可簡單將 node_modules 下的 Petite-vue mount 到 static 目錄下,如此可繼續使用 NPM 管理 Petite-vue 版本,不必再手動將 Petite-vue 複製到 static 目錄下,此方法也適用於其他 NPM 套件
  • Petite-vue 也支援 ESM,因此也可使用 import ,開發體驗與 Vue 類似
  • Petite-vue 也可使用 Composition API 開發
  • Petite-vue 特別提供 $delimiters,讓我們可以避開 Go template 所使用的 delimiter