點燈坊

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

整合 Hugo 與 Vue 3

Sam Xiao's Avatar 2024-01-22

使用 Module Mount 與解決與 Go Template 的 Delimiter 之後,Vue 3 也可搭配 Hugo 使用。

Version

Hugo 0.121.2
Vue 3.4

New Site

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

Install Vue 3

$ npm install -D vue
  • 使用 NPM 安裝 Vue 3

Module Mounts

hugo.json

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

Line 5

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

Layout

layouts/index.html

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

<script type="module">
import { createApp, ref } from './js/vue.esm-browser.prod.js'

let count = ref(0)

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

createApp({
  delimiters: ['[[', ']]'],
  setup: () => ({
    count,
    onClick
  })
}).mount('#app')
</script>

Line 6

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

Line 13

<div>[[ count ]]</div>
  • 顯示 Vue 變數

Vue 使用與 Go template 不同的 delimiter

Line 18

<script type="module">
  • 使用 ESM 寫 Vue

Line 19

import { createApp, ref } from './js/vue.esm-browser.prod.js'
  • vue.esm-browser.prod.js 引用出 createApp()ref(),這是使用 Vue 最重要的兩個 function

Line 25

createApp({
  delimiters: ['[[', ']]'],
  setup: () => ({
    count,
    onClick
  })
}).mount('#app')
  • createApp():統整所有 state 與 method,必須將所有 statemethod 都在 setup() 內宣告
  • mount():最後加上 mount() 綁定到 HTML,必須要傳入指定 HTML 的 id

Line 26

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

Line 21

let count = ref(0)
  • 使用 ref() 宣告 count state

Line 23

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

Conclusion

  • Hugo 也可以整合 Vue 3,不過相較起來,Petite-vue 的語法還是比 Vue 3 精簡,若沒用到 Vue 3 的功能,可以選擇 Petite-vue 即可
  • 使用 Module Mount 可簡單將 node_modules 下的 Vue mount 到 static 目錄下,如此可繼續使用 NPM 管理 Vue 版本,不必再手動將 Vue 3 複製到 static 目錄下,此方法也適用於其他 NPM 套件
  • Vue 3 特別提供 delimiters,讓我們可以避開 Go template 所使用的 delimiter