Loading 4%

Nuxt Content 做網站的資料管理【1】

Nuxt Content 是一個能在 Nuxt 專案中,快速建立內容資料管理流程的套件。套件提供 API 查詢集合或單筆資料、並且提供元件直接渲染內容,在內容上可以做客製化變動,針對達到小型資料管理並顯示內容的專案可以試試。

前言

這系列不是從 0 開始的教學文章,而是我在開發個人網站紀錄,希望可以幫助或分享給有需求的人。

上一篇有稍微提到,我希望在目前階段能夠 快速且簡單地建立內容管理流程,因此選擇了 Nuxt Content,這篇我整理實際在網站中重點使用到 Nuxt Content 的地方。

怎麼設定 Markdown 資料

Nuxt Content 可以直接讀取 Markdown 檔案,並在檔案開頭透過 ---(front matter)定義內容結構。我先依照官方文件完成基本設定,再依照實際頁面需求,放入畫面上會用到的欄位。

以下是我目前在網站中實際使用的欄位:

  • title & description: 用在文章列表呈現、搜尋結果、文章內頁
  • category & tags : 用在分類頁、文章側邊欄區塊
  • image: 用在首頁、文章列表圖片呈現
  • date: 用在首頁近期文章與列表文章排序

下面截取系列第 0 篇文章的 front matter 作為例子:

how-this-project-was-planned.md
      ---
title: '【0】這個專案怎麼規劃的?'
description: '2020 我的個人網站產生後,經歷 5 年再度回歸初心重新來過,並結合 Blog 與這些年累積技術,這篇文章就來說為何重做?這次做了什麼規劃、技術。'
category: 'Nuxt 個人網站實戰紀錄'
tags: ['Nuxt']
image: /images/posts/個人網站實戰紀錄.jpg
date: 2026-01-13
---
## 回到過去~為什麼會想「重做」而不是「改版」
當我開啟 2020 個人專案
....

    

front matter 結構設定好後,新增文章時只要複製一份再調整欄位內容與文章內容,就能顯示在設定的區塊上。不過欄位並不是一開始就全部想好,而是隨著功能開發逐步補齊

因此在製作畫面初期,我先建立兩篇測試文章,讓文章相關區塊能先正常顯示,也方便後續同步調整資料結構。

怎麼顯示文章列表

Nuxt Content 提供的 queryCollection是我在網站中查詢與取得內容資料的主要方式。我把它當成一個「資料 API」,先在 composables 函式整理好我要的資料,再交給元件負責畫面呈現。

下圖是我的文章列表頁面截圖,每一篇文章會顯示標題、摘要、分類、圖片等資訊,並且有兩個影響列表呈現的功能分別是排序頁數

usePosts.ts
      const { data: allPosts } = await useAsyncData(`${collection}-${limit}-data`,() => {
   return queryCollection(collection).order(...).select(...).limit(...).skip(...).all();
});

    

在資料的處理上,我主要使用了幾個方法:

  • .order():依照 date 欄位做新舊排序
  • .select():只取列表需要顯示的欄位
  • .limit() & .skip(): 控制每頁資料數量與分頁位置
  • .all():最後取得符合條件的文章集合

我刻意把資料層全部包成 composables,讓元件只專心處理畫面。 這樣之後不論是新增分類、改排序功能,都只需要改一個地方,不會每個頁面都跟著調整,對後續維護跟擴充都比較友善。

怎麼顯示文章內容

在文章內頁中,我同樣使用 queryCollection ,並搭配 .path() 與 .first() 取得單筆資料。

usePostDetail.ts
      export const usePostDetail = (collection: "blog" | "notes", path: string) => {
  return useAsyncData(path, () => {
    return queryCollection(collection).path(path).first();
  });
};

    

在資料的處理上,我主要使用了幾個方法:

  • .path():path 會依造基本設定 (content.config.ts) 生成路由
  • .first():只取第一筆符合資料

資料取得後,需要一個能將 Markdown 轉 HTML 的方法,這部分 Nuxt Content 已經內建處理好,我需要使用 ContentRenderer 元件。

內容我將取得文章資料的方式調整為 composable,並以文章路徑作為 key,主要是為了解決 middleware 與頁面初始化造成的重複請求問題。

TailwindCSS Typography 文章快速排版

當內容能正常顯示後,接下來就是樣式問題。專案本身已經使用 TailwindCSS,但如果文章要自己處理排版,其實會花不少時間。

我使用TailwindCSS擴充套件Typography,它可以快速替文章內容套用基本排版樣式。完成安裝與設定後,只要在外層加上 prose 類別,這樣就能快速讓 Markdown 內容有基本的閱讀排版。

detail.vue
      <template>
<!-- ...略過 -->
    <section class="prose max-w-full dark:prose-invert">
    <ContentRenderer :value="post" />
    </section>
<!-- ...略過 -->
</template>

    

站內搜尋的實作情境

輸入關鍵字後,我同樣使用 queryCollection ,並搭配 .orWhere() 方法尋找符合關鍵字。

useSearch.ts
      const fields = ["title", "description"]
const list = await queryCollection(collection)
    .orWhere((q) => {
        for (const field of fields) {
            q.where(field, "LIKE", `%${keywordsToLower.value}%`);
        }
        return q;
    })
    .select(...)
    .all();

    

在資料的處理上,我主要使用了幾個方法:

  • .orWhere:新增 or 群組,fields 搜尋指定欄位裡有沒有LIKE符合我輸入關鍵字
  • .select() & .all(): 上面已說明

在針對一開始與關鍵字為空情況,需要在判斷關鍵字是為空去進行 .slice() 限制前面幾篇文章顯示,就不會一開始搜尋區塊沒有預設文章。

useSearch.ts
      if (keywords.value === "") {
    return list.slice(0, LIMIT_COUNT) || [];
}

    

搜尋不只服務單一頁面,而是全站共用的功能,所以我將查詢邏輯集中在 composables。 無論是文章、分類或標籤搜尋,都能共用同一層邏輯,避免搜尋規則分散在各個元件中。

總結

在這個專案中,Nuxt Content 提供的 API 與元件,讓我可以在前端就完成內容查詢與渲染內容,不需要額外建立資料庫或撰寫轉檔流程,就能完成文章列表、內頁與搜尋功能。

對於個人網站或小型內容專案來說,這樣的開發方式相對輕量,也能保有不錯的彈性與可維護性。

下一章會分享我在 Nuxt Content 上的進階設定,以及實際開發過程中遇到的一些問題與解法,作為這一段內容管理實作的延伸。

留言板