前言
把一組靜態 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,再把每一塊內容問四個問題:
- 是否跨頁共用?是的話先進全域 asset、layout、header 或 footer。
- 是否是商家會獨立移動的內容帶?是的話做成 section。
- 是否會在同一 section 內重複?是的話做成 block。
- 是否有 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 個RemoteAssetwarning,皆來自外部字型資源。
原始碼還能證明首頁 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?
參考資料
- Shopify:Theme architecture
- Shopify:Layouts
- Shopify:JSON templates
- Shopify:Sections
- Shopify:Section groups
以上平台文件查核日期:2026-07-29。
