前言

把一組靜態 HTML 放進 Shopify Theme,真正困難的通常不是把副檔名改成 .liquid,而是重新分配責任:哪些樣式是全站共用、哪些畫面是 Theme Editor 可調整的 section、哪些重複項目要做成 block、哪些內容應該由 Shopify resource 提供,以及模板如何保存商家排好的 section 順序。

上一篇談的是 Shopify GDPR Webhook 的處理與交付紀錄。這篇開始進入另一個實際案例:一份包含首頁與多個內容頁的 static source archive,如何逐步轉成 Online Store 2.0 Theme。

公開內容只保留架構與驗證方式,不搬用原始品牌、人物、圖片、正式商店或設計文案。

原本的做法與問題症狀

靜態 archive 每個頁面都能單獨開啟,CSS、圖片與互動也已經靠近設計稿。若直接逐頁複製,短期看起來最快,卻會產生四種症狀:

  • Header、Footer、按鈕與設計 token 在每頁重複,改一次品牌色要同步多份檔案。
  • 標題、圖片、連結與卡片都寫死在 HTML,商家只能請開發者改碼。
  • 新聞、政策文章與商品卡只是靜態字串,無法自然接到 Shopify Blog、Product 或 Collection。
  • 首頁 section 的順序被 DOM 固定,Theme Editor 即使能改文字,也不能安全地新增、移除或重排內容。

另一個常見做法是把整頁塞進一個超大的 section。它雖然能出現在 Theme Editor,實際上仍是一份難以維護的靜態頁:schema 過長、設定名稱失去語意,任何局部修改都可能影響整頁。

問題是怎麼推敲出來的?

案例先把 static archive 視為「視覺與互動契約」,而不是最終程式架構。轉換計畫逐頁建立 source-to-surface map,再把每一塊內容問四個問題:

  1. 是否跨頁共用?是的話先進全域 asset、layout、header 或 footer。
  2. 是否是商家會獨立移動的內容帶?是的話做成 section。
  3. 是否會在同一 section 內重複?是的話做成 block。
  4. 是否有 Shopify 原生生命週期?新聞、商品與商品群組優先考慮 Blog、Product、Collection,而不是複製資料。

來源 tree 也提供了可核對的落地證據:全域 wrapper 放在 layout/theme.liquid,共用 CSS/JavaScript 與圖片放在 assets/,首頁拆成 Hero、理念卡、分類紀錄、動態清單與支持區塊等多個 section,templates/index.json 則只保存 section instance、設定、blocks 與 order。

這個拆法對應 Shopify 現行 Theme architecture:layout 是頁面外框,JSON template 描述 section 組合,section 以 schema 暴露設定,snippet 則負責不需要由商家直接排列的可重用 Liquid。

最後採用的架構

案例採用的責任分層如下:

static source archive
  → 畫面、互動、responsive 與素材清單的比對基準

layout/theme.liquid
  → HTML shell、全站資源、header/footer section groups

assets/
  → 共用 CSS、JavaScript、字型策略與匿名化素材

sections/
  → 可獨立設定與排列的內容帶
    → section settings:標題、說明、CTA、主圖
    → blocks:卡片、事件、紀錄、連結

templates/*.json
  → 每種頁面的 section instances、設定值與顯示順序

Shopify resources
  → Blog/Article、Product/Collection、Menu

這裡的「轉版」不是一次把所有 HTML 消滅,而是保留 source archive 當視覺回歸基準;正式 theme 不再從 archive runtime 載入任何畫面。

關鍵實作

首頁 template 不放 Liquid markup,只指定 section type 與順序:

{
  "sections": {
    "hero": { "type": "campaign-home-hero", "settings": {} },
    "stories": {
      "type": "campaign-story-cards",
      "blocks": {},
      "block_order": []
    }
  },
  "order": ["hero", "stories"]
}

Section 則把不可變的 layout 與可編輯內容分開:

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

  {% for block in section.blocks %}
    <article {{ block.shopify_attributes }}>
      <h3>{{ block.settings.title }}</h3>
      <p>{{ block.settings.body }}</p>
    </article>
  {% endfor %}
</section>

圖片也採兩段式策略:Theme Editor 已選圖片時使用 image_picker 的值;尚未完成內容搬移時才使用 theme asset fallback。Fallback 是轉換期護欄,不應永久變成兩份內容來源。

共用設計 token 與互動移到全域 asset,避免每個 section 各帶一套相似 CSS/JavaScript。只有和單一 section 緊密相關、而且能安全隔離的行為,才留在對應 component 範圍。

實際驗證

2026-07-29 使用 Shopify CLI 4.5.2 對來源 theme 執行 shopify theme check

  • 44 個 theme files 完成檢查。
  • 指令 exit code 為 0。
  • 沒有 error。
  • layout/theme.liquid 有 3 個 RemoteAsset warning,皆來自外部字型資源。

原始碼還能證明首頁 JSON template 由多個 section 組成,重複卡片使用 blocks,圖片與連結已暴露為 section/block settings,header 使用 Shopify menu setting。

但這次驗證不能證明整份多頁轉換計畫已完成。來源目前有客製首頁 sections,也有 skeleton theme 的 Blog、Article、Product 與 Collection 基礎 surface;計畫中的其他客製頁面與 resource migration 沒有足夠實作證據,因此不能寫成已交付。

仍然存在的限制

第一,Theme Check 是靜態分析,不會比較 static source 與 theme preview 的像素、互動或 responsive 行為。

第二,外部字型雖只產生 warning,仍可能帶來效能、隱私、內容安全政策與第三方可用性風險。正式專案應評估改由 Shopify CDN/theme assets 供應,或至少建立可接受的 fallback。

第三,JSON template 的預設內容只是初始值。商家在 Theme Editor 儲存後,正式設定可能與 repository 不同;部署 theme code 不等於同步商店內所有內容設定。

第四,目前來源工作區沒有可用的 Git history,因此這批只能以 conversion plan、source tree、Liquid/JSON 實作與當日 Theme Check 作證,不能虛構 commit 演進。

最後,多頁 static archive 仍需要逐頁建立 resource 與 template 對照。首頁轉成功不代表 Blog、Article、Contact 與 Product journey 都已完成。

可以延伸到哪些情境?

這個方法也適合把 Figma export、活動 landing page 或舊 CMS template 搬進 Shopify:

  • 先凍結 source archive,避免轉換期間基準持續漂移。
  • 建立 page/surface map,再拆 global、section、block 與 resource。
  • 先完成一條可預覽的 vertical slice,確認 Theme Editor 與 responsive 策略。
  • 每完成一種 surface,就補 Theme Check、視覺比對與商家編輯驗收。

下一篇會深入 section 內部的編輯模型:如何把一頁式設計拆成 Shopify 可編輯的 Sections 與 Blocks?

參考資料

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