Shopfiyテーマでレイアウトファイルから各セクションを読み込む方法

本記事は私達の会社で作ったShopifyテーマ開発入門書『Hello Shopify Themes Shopifyテーマ開発ガイド』からの抜粋です。


こんにちは。エンジニアの川島です。5月なのに肌寒い日が続いており、そろそろ五月晴れが恋しいです…。
執筆を担当したShopifyテーマ開発入門書『Hello Shopify Themes Shopifyテーマ開発ガイド』が販売開始となり、ご感想など、社内で嬉しく拝読しています。ありがとうございます!

1-3. テーマファイルの水先案内

一章の締めくくりとなる本節では、テーマファイルの内部に踏み入り、どのようなLiquid/JSONの記述によって各ファイルが組み合わされているのかを、ざっくりと解説します。テーマ開発の際に、いわば目印となるようなポイントです。
頭の片隅に留めておくだけでも、テーマ開発に取り組みやすくなるかと思います。

実際のコードを見ながら読み進めたい方は、DawnテーマのGitHubリポジトリを参照してください。

DawnテーマのGitHubリポジトリ
https://github.com/Shopify/dawn

レイアウトファイルの構成

レイアウトファイルlayout/theme.liquidは、前節で紹介したとおり、テーマ全体の基盤を担うLiquidファイルです。
サンプルコードを次に示します。
※Dawnのlayout/theme.liquidを、分かりやすいように簡素化したものです。実際の記述とは異なります。

▼layout/theme.liquid

<!doctype html>
<html>

  <head>
    <meta charset="utf-8">
    //略
    {% render 'meta-tags' %}
    <script src="{{ 'global.js' | asset_url }}" defer="defer"></script>
    //略
  </head>

  <body>
    {% section 'header' %}
    <main id="MainContent" role="main">
      {{ content_for_layout }}
    </main>
    {% section 'footer' %}
    <script>
      //JavaScriptグローバル変数定義
      window.shopUrl = '{{ shop.url }}';
      //略
    </script>
  </body>

</html>

ここでは、次の要素に注目してください。

  • {{ content_for_layout }}
  • {% section 'header' %}{% section 'footer' %}
  • {% render 'meta-tags' %}
  • {{ 'global.js' | asset_url }}

{{ content_for_layout }}

<main>タグをみると、{{ content_for_layout }}という記述のみで、その他のHTML要素はありませんね。
この{{ content_for_layout }}が、各ページテンプレートのコンテンツの出力を担っています。レイアウトファイルにしか記述できません。
商品ページではtemplates/product.json、ブログ記事ページではtemplates/article.jsonといったように、ページ種別に適したテンプレートのコンテンツ内容が、ここに表示されます。

テーマファイルの読み込み

{% section %}{% render %}{{ asset_url }}はすべて、テーマファイルの読み込みを表しています。
セクション・スニペット・アセットの3ファイルは明示的に読み込まなければ表示されないことと、テーマファイルの階層構造ルールに沿って読み込む必要があることは、前節で紹介しましたね。レイアウトファイルでは、セクション・スニペット・アセットの3ファイルを読み込めます。1つずつ概要を見てゆきましょう。

{% section 'セクションファイル名' %}

読んで字の通り、セクションの読み込みを行っているのが、この{% section 'セクションファイル名' %}です。Liquidタグのひとつで、セクションタグと呼ばれます(※HTMLのセクションタグ<section>とは無関係です)。
{% section 'header' %}は、sections/header.liquidファイルを読み込みます。

{% render 'スニペットファイル名' %}

スニペットファイルは{% render 'スニペットファイル名' %}形式のLiquidタグで読み込みます。
{% render 'meta-tags' %}は、snippets/meta-tags.liquidファイルをレンダリングしています。

{{ 'アセットファイル名' | asset_url }}

さて、セクションファイルとスニペットファイルがLiquidタグで読み込む以上、アセットファイルも……? と思うところですが、画像・CSS・JavaScriptといったアセットファイルは、{{ 'アセットファイル名' | asset_url }}形式で読み込みます。
これはLiquidのアセットフィルターという記法で、asset_url部分を書き換えることによって、出力データをさまざまな形式に加工できます。

テンプレートファイル(JSON)のデータ構造

各ページのテンプレートファイルも内部を見てゆきましょう。
OS2.0によって、テンプレートファイルはLiquidとJSONふたつのファイル形式が使えるようになりました。Dawnなど、OS2.0対応テーマでは基本的にJSON形式のテンプレートが用いられています。
次に示すのは、DawnのコレクションページのJSONテンプレートファイルです。

▼templates/collection.json

{
  "sections": {
    "banner": {
      "type": "main-collection-banner"
    },
    "product-grid": {
      "type": "main-collection-product-grid"
    }
  },
  "order": [
    "banner",
    "product-grid"
  ]
}

HTMLやLiquidの記述は全く無いのがわかりますね。ここで、JSON内の"sections"に注目してください。
"sections"部分で定義されているのは、このテンプレートに読み込むセクションの一覧です。JSONテンプレートでは、Liquidタグ{% section %}ではなく、このJSONデータによってテンプレートに読み込むセクションを決定します。

このtemplates/collection.jsonで読み込まれるセクションは、sections/main-collection-banner.liquidsections/main-collection-product-grid.liquidの二点です。
それぞれの記述をもう少し分かりやすく置き換えてみます。

{
  "sections": { //テンプレートに読み込むセクション一覧
    "任意のID名_A": {
      "type": "セクションのファイル名_A"
    },
    "任意のID名_B": {
      "type": "セクションのファイル名_B"
    }
  },
  "order": [ //テンプレートに読み込むセクションの順序
    "任意のID名_A",
    "任意のID名_B"
  ]
}

元のtemplates/collection.jsonと見比べてみてください。なんとなく、それぞれの記述の意味が伺えるでしょうか。
より詳しい解説は、四章で後述します。

補足:Liquidテンプレート

テンプレートファイルは、Liquidファイル形式のものも使えます。
JSON形式との差異を次にまとめました。

※スマホの方は横スクロールしてください

JSONテンプレート Liquidテンプレート
Liquid/HTMLの記述 できない できる
セクション読み込み JSONに記述 {% section %}タグ
テーマエディタからセクションを自由に追加 できる できない

セクションファイルのLiquidとスキーマ

さて、最後にセクションファイルの内部を見てゆきましょう。
Dawnにおけるセクションの例として、ヘッダーやフッター、TOPページのメインビジュアル、テキスト付き画像バナーなどが挙げられます。テーマエディタから何らかの操作を行いたいパーツは、セクションファイルを用いて実装します。

テーマエディタのキャプチャ画像
サイドバーの「情報バー」「ヘッダー」「画像バナー」「商品コレクション」……などが全てセクションを表している。セクションごとに、テキストや画像などのコンテンツをテーマエディタから登録・更新できる

セクションファイル内の記述によって、テーマエディタから操作できる項目は変わります。
シンプルな構成のセクションファイルのサンプルコードは次のとおりです。

<section>
  <h1>{{ section.settings.title }}</h1>

  {% if section.blocks != blank %}
    <ul>
      {% for block in section.blocks %}
        <li>{{ block.settings.title }}</li>
      {% endfor %}
    </ul>
  {% endif %}

</section>

{% schema %}
{
  "name": "Section Sample",
  "settings": [
    //略
  ],
  "blocks": [
    //略
  ],
  "presets": [
    {
      "name": "Section Sample"
    }
  ]
}
{% endschema %}

見慣れないタグがいくつかありますね。ここでは次の要素に注目してください。

  • {% schema %}タグ
  • {{ section.settings.title }}{{ block.settings.title }}
  • {% if %}{% for %}タグ

テーマエディタと関連づける{% schema %}タグ

セクションをテーマエディタから操作するために欠かせないのが、この{% schema %}タグです。記述は必須ではないものの、{% schema %}の記述がないセクションは、テーマエディタの操作対象から除外されます。

{% schema %}タグ内部はJSONで記述されています。
settingsblocks部分は、該当セクションをテーマエディタで開いた際、サイドバーに表示される設定項目の定義です。
presetsの記述があると、該当セクションをテーマエディタからノーコードでJSONテンプレートに追加できるようになります。

より詳しくは「3-2.動的セクションとブロックの作成」と四章で解説しますので、現時点では「テーマエディタとの連携に必要なんだな」くらいのざっくりとした認識で大丈夫です。

セクション設定とブロック設定

{{ section.settings.title }}{{ block.settings.title }}は、それぞれセクション設定とブロック設定を表すLiquidオブジェクトです。テーマエディタから登録されたコンテンツをここに出力します。
セクション設定とブロック設定については「1-1.テーマ概要」のテーマエディタ解説パートでも少し紹介しましたね。
セクション設定は該当セクションの共通設定を、ブロック設定はセクション内の繰り返し要素(カルーセルスライダー内におけるスライドのような、数量可変の子要素)に関する設定を表します。

セクション設定とブロック設定は、{% schema %}タグ内の記述によって、どのような設定にするか——たとえば、テーマエディタから入力できるコンテンツの種別(画像・テキスト・URLなど)、テーマエディタ上に表示する入力UI(テキストボックスやラジオボタンなど)——を決定できます。
こちらも詳しくは四章で解説します。

条件判定とループ出力のLiquidタグ

これはセクション固有の記述ではないですが、テーマ開発で頻出するLiquidタグ{% if %}{% for %}についても本節で概要を紹介しておきます。より詳しい記法は四章を参照してください。
{% if %}は条件判定を、{% for %}は反復出力を表します。

{% if 条件判定式 %}〜{% endif %}

条件判定に用いるLiquidタグはいくつかありますが、もっとも分かりやすいのが{% if %}タグでしょう。プログラミングロジックで言うところのif文を生成し、条件判定結果がtrueの場合のみ、内部のコードを出力・実行します。

先ほど例に挙げたセクションファイルのサンプルコード内のif文は、セクションのブロック配列section.blocksが空ではない場合のみ、<ul>以降のコードを出力・実行します。

{% if section.blocks != blank %}
  //section.blocksが空でなければ以下のコードを出力・実行
  <ul>
    {% for block in section.blocks %}
      <li>{{ block.settings.title }}</li>
    {% endfor %}
  </ul>
{% endif %}

{% for 要素 in 配列 %}〜{% endfor %}

プログラミングロジックのfor文を表す{% for %}タグは、配列に含まれる要素の数だけ、内部のコードを繰り返し出力・実行します。
次に示すサンプルコードのfor文は、セクションに登録されたブロックの数だけ——カルーセルスライダーにおけるスライドの数を想像してください——<li>タグを繰り返し出力します。

<ul>
  {% for block in section.blocks %}
    //section.blocks配列に含まれる子要素の数だけループし、以下のコードを出力・実行
    <li>{{ block.settings.title }}</li>
  {% endfor %}
</ul>
ちょっと休憩
ここまで駆け足で、テーマの概要と構造について触れてきました。一気読みした方、疲れていませんか?
テーマ開発未経験の方は、初めて触れる用語が多くて混乱する部分もあったかもしれません。
本章で紹介した内容を、一度にすべて把握する必要はありません。実際にテーマ開発を始めてみて、分からない要素が出てきたら、改めて本章を読み返してみてくださいね。

さて、珈琲を飲んで一息ついたら、テーマ開発のための環境構築を始めましょう。


第1章の無料公開シリーズは本記事で締めくくりとなります。お読みいただきありがとうございました!
第2章以降で掲載している内容の詳細は、こちらの記事で詳しく紹介しています。
ご関心があれば、書籍の方もぜひお役立ていただければ幸いです。どうぞよろしくお願いします!

本書のご購入はこちらの特集ページから承っております。
完売後の増刷予定は現時点ではございません。印刷書籍をご希望の方は、ぜひお早めにお迎えください。

  • 著者:川島さやか
  • 出版:non-standard world, Inc.
  • 判型・ページ数:B5判・248ページ
  • 価格:3,850円(税込)※PDF版同梱、送料無料

特集ページへ

記事カテゴリー