前言

上一篇 先把 static archive 拆成 layout、assets、sections、templates 與 Shopify resources。接下來真正會影響長期維護的是:一個畫面到底該拆成幾個 sections?哪些欄位放 section settings?哪些資料做成 blocks?

拆得太少,Theme Editor 只看到一個巨大表單;拆得太細,商家會面對數十個沒有上下文的小元件。這篇用實際首頁的 Hero、理念卡、分類紀錄、動態清單與支持區塊,整理出一套可重複使用的判斷方式。

原本的做法與問題症狀

Static HTML 常把整頁內容直接寫在 DOM:

hero
  heading + body + two buttons + image
cards
  card + card + card
records
  tab + tab + repeated rows
events
  repeated links + featured item

若只把文字替換成一長串 section settings,重複卡片仍有固定數量;商家不能新增第四張、刪除第二張或調整順序。反過來,如果連每個按鈕、icon 與文字段落都做成獨立 block,Theme Editor 的結構會和讀者看到的視覺分組脫節。

案例中還有一個更隱性的問題:部分列表需要「分類」。最初 static UI 是 tabs 加卡片,但 Shopify section block 本身只是一層清單。若沒有清楚的 group key,Liquid 很難知道哪張卡屬於哪個 tab。

問題是怎麼推敲出來的?

案例用「誰控制生命週期」來切:

  • Section 是商家會整段移動、隱藏或複製的內容帶。
  • Section settings 控制這一段唯一的內容,例如 eyebrow、標題、說明、主圖與 CTA。
  • Blocks 控制同型、可新增/刪除/重排的項目,例如卡片、事件或紀錄。
  • JSON template 保存 section instances、block instances 與顯示順序。
  • Shopify resource 負責本來就有獨立生命週期的內容,不應為了 Theme Editor 方便再複製一次。

來源首頁正好呈現不同形狀:

  • Hero 沒有重複項目,只需要 section settings。
  • 理念卡、動態連結與支持卡片使用 blocks。
  • 分類紀錄以 block 的 group setting 表示歸屬,再由 Liquid 依 group 分面。
  • Template 的 orderblock_order 保存預設排列。

分類字串是一個務實的 local model,不代表 Shopify 平台只有這種做法;若內容需要真正巢狀、跨頁查詢或獨立權限,就應重新評估 theme blocks、metaobjects 或 Shopify resources。

最後採用的架構

一個可編輯 section 的資料流如下:

templates/index.json
  → section instance + 初始設定 + section order

sections/feature-list.liquid
  → 固定 HTML 語意與 layout
  → section.settings:唯一標題/說明/CTA
  → section.blocks:可重複卡片
  → block.shopify_attributes:Theme Editor 選取定位

Theme Editor
  → 商家新增、移除、修改、重排
  → 商店端保存實際 section data

Schema 不是把所有 CSS 都開放,而是定義安全編輯範圍。版面 grid、heading hierarchy、focus state 與 responsive behavior 仍由 theme code 維護;商家只控制具有內容語意的設定。

關鍵實作

一個卡片列表可以這樣定義:

<section aria-labelledby="feature-title-{{ section.id }}">
  <h2 id="feature-title-{{ section.id }}">
    {{ section.settings.title }}
  </h2>

  <div class="feature-grid">
    {% for block in section.blocks %}
      <article {{ block.shopify_attributes }}>
        {% if block.settings.image != blank %}
          {{ block.settings.image
            | image_url: width: 720
            | image_tag: loading: 'lazy', alt: block.settings.title
          }}
        {% endif %}
        <h3>{{ block.settings.title }}</h3>
        <p>{{ block.settings.body }}</p>
      </article>
    {% endfor %}
  </div>
</section>

{% schema %}
{
  "name": "Feature list",
  "settings": [
    { "type": "text", "id": "title", "label": "Title" }
  ],
  "blocks": [
    {
      "type": "feature",
      "name": "Feature",
      "settings": [
        { "type": "image_picker", "id": "image", "label": "Image" },
        { "type": "text", "id": "title", "label": "Title" },
        { "type": "textarea", "id": "body", "label": "Body" }
      ]
    }
  ],
  "presets": [{ "name": "Feature list" }]
}
{% endschema %}

presets 決定這個 section 是否能由商家從 Theme Editor 新增,以及新增時的合理起點;template 內的 instance 則是特定頁面的預設組合。兩者不能混為一談。

對分類紀錄,案例沒有在 Liquid 裡寫死「第一個 tab 顯示前三張卡」,而是讓每個 block 帶一個受控 group value:

{% for block in section.blocks %}
  {% if block.settings.group == active_group %}
    {% render 'record-card', block: block %}
  {% endif %}
{% endfor %}

這比依 index 分組穩定,因為商家重排 block 後,分類不會跟著錯位。

實際驗證

來源檔案可靜態證明:

  • Hero 只使用 section settings,沒有假裝存在可重複內容。
  • 三類重複清單都透過 section.blocks 迭代。
  • 多個 block markup 帶有 block.shopify_attributes,供 Theme Editor 對應畫面中的 block。
  • templates/index.json 同時保存 section order 與各 section 的 block_order
  • 圖片設定使用 image_picker,連結使用 url,導覽使用 Shopify menu setting。
  • 2026-07-29 的 Theme Check 對 44 個檔案完成靜態分析,沒有 error。

不過,來源沒有今天可公開的 live Theme Editor 操作紀錄。因此「schema 能被解析」與「JSON 結構存在」已驗證;商家是否能在 preview 中順利新增 section、拖曳每個 block、儲存後重開仍保留,尚未由這批證據證明。

仍然存在的限制

第一,設定越多不代表越好。讓商家調整任意 margin、font size、position 與 animation,會把設計系統變成一組難以測試的 page builder。

第二,fallback asset 與 merchant-selected image 同時存在時,要定義移除 fallback 的時機;否則開發預設內容與正式內容會長期並存。

第三,分類 block 使用 group key 很適合小型固定 taxonomy,但 group 名稱變更、跨 section 共用或項目數快速成長時,維護成本會升高。這時應把資料提升成 resource 或 metaobject。

第四,block.shopify_attributes 應在可選取的 block 根節點一致使用。案例並非所有迴圈都能證明已補齊,正式 editor QA 仍要逐一點選。

最後,template JSON 可能由 Shopify admin Theme Editor 更新。若團隊同時直接改 repository 的 JSON 預設值,需要先決定 code 與 store configuration 的同步規則,避免互相覆蓋。

可以延伸到哪些情境?

拆 section/block 時可以使用這個簡短準則:

整段可移動?          → section
同段內可重複?        → block
只有一份內容?        → section setting
跨頁、可查詢、有生命週期? → Shopify resource / metaobject
純呈現重用?          → snippet 或 theme block

下一篇會處理最容易混淆的資料層:Shopify Theme 內容該用 Blog、Product、Collection 還是 Metafield?

參考資料

以上平台文件查核日期:2026-07-29。