Shopify Theme × Tailwind CSS を考える

# この記事について

この記事は、Shopify テーマに　Tailwind CSS を導入することについて思うことや導入の手順などについて解説しています。
普段、業務の中で Shopify テーマに Tailwind CSS を導入してフロント開発を行うことが多いので、その辺のノウハウ共有になれば幸いです。

現時点での、自分が考えるベストプラクティスについても紹介していますので、ぜひ最後まで読んでいただけると嬉しいです。
株式会社 UnReact アドベントカレンダーの初日です。張り切っていきたいと思います！！

## 読者の前提条件

- Mac OS　または Linux（WSL2を含む） を使用している
- Tailwind CSS についての基礎知識がある
- Shopify テーマについての基礎知識がある
- Homebrew を導入している
- Node.js や npm の環境構築をしている

Homebrew を導入していない方は、公式サイトを参考にインストールしておきましょう。Shopify CLI のインストールに使用します。

https://brew.sh/index_ja

Node.js / npm は、Tailwind CSS の導入にあたり必要になります。
もしこれから環境構築をしようと思っている方は、 Volta での環境構築がおすすめです。

https://zenn.dev/taichifukumoto/articles/how-to-use-volta

# Shopify と Tailwind CSS の相性

そもそも、Shopify テーマと Tailwind CSS の相性（組み合わせ）は、良いと言えるのでしょうか。

持論にはなりますが、私は「**相性が良い**」と感じています。

普段の業務の中でも Shopify テーマをベースにしたフロント開発では、必ずと言っていいほど Tailwind CSS を導入して開発を行います。

そもそも、Tailwind CSS は React などのコンポーネントベースのライブラリやフレームワークと相性が良いです。これは、Tailwind CSS の DRY じゃないというデメリットを、コンポーネントの使い回しによって解消できるためです。

Shopify テーマも Section や Snippet といった使い回すことを前提とした部品単位の構成となっているため、Tailwind CSS と相性が良いと感じています。

微妙だなと感じている点は、色の指定が Shopify テーマのシステムにハマっていないなと感じる点です。
通常のテーマでは、「テーマ設定」でテーマ全体の色を指定できるようになっています。Tailwind CSS では、デフォルトのカラーパレットや `tailwind.config.js` でカスタムしたカラーを使用することができます。
`tailwind.config.js` に Shopity のテーマ設定を組み込むことができれば良いのですが、できないんですよね。

解決策として、既存のテーマに　Tailwind CSS を用いて作った Section を組み込む場合は、テーマエディタ（ノーコード）のセクションの設定項目でカラーを編集できるように `schema` を書いています。

2021年6月のアップデートで実装された GitHubとの連携も相まって、Tailwind CSS での開発は以前より行いやすくなりました。

上記の理由から、Shopify と Tailwind CSS は相性がいいと考えています。

:::note
最近 Shopify から発表された Hydrogen という　へッドレスコマース（公式はダイナミックコマースと言っている）のフレームワークにも Tailwind CSS が採用されていました。
フレームワークは　React ベースということもありますが、Shopify 公式も Tailwind CSS 推しなのかもしれません。
:::

それでは実際に　Shopify テーマに Tailwind CSS を導入する際の手順について解説していきます。

# 既存の Shopify テーマ × Tailwind CSS の開発

まずは、1番多いパターンかと思われる既存のテーマに Tailwind CSS を導入して、フロント開発を行う場合について説明していきます。

:::note warn
以下の手順は、OS 2.0　に対応したテーマを前提とした手順となっています。
:::

## Shopify CLI をインストールする

Shopify CLI をインストールします。既にインストールされている方は、飛ばしてください。

公式に記載の Homebrew を使用する方法でインストールします。

```shell:Terminal
# 公式以外のリポジトリをフォーミュラとしてHomebrewに追加する
$ brew tap shopify/shopify

# shopify-cliをHomebrewでインストール
$ brew install shopify-cli
```

インストール完了後、以下のコマンドでバージョン番号表示されればOKです。

```shell:Terminal
$ shopify version
```

詳しくは公式の [Install Shopify CLI](https://shopify.dev/themes/tools/cli/installation) をご覧ください。

## Shopify CLI でストアにログインする

Shopify CLI 上で、ローカルに持ってきたいテーマがあるストアにログインします。

```shell:Terminal
$ shopify login --store 〇〇.myshopify.com
```

`〇〇.myshopify.com` には、ログインしたいストアの URL を入れてください。
ブラウザが開き、アカウントのログイン画面が表示されますので、ログインしましょう。ブラウザ上でのログインが完了したら、ブラウザは閉じて大丈夫です。

ログインに使用できるパートナーアカウントが複数ある場合は、ターミナル上で選択を促されますので、ログインに使用するアカウントを選択します。

```shell:Terminal
? Select partner organization (Choose with ↑ ↓ ⏎, filter with 'f')
> 1. Your Partner Account Name (0000000)
  2. ...
```

ストアへのログインが成功すると以下のメッセージが表示されます。

```shell:Terminal
Logged into store 〇〇.myshopify.com.myshopify.com in partner organization Your Partner Account Name
```


## ローカルにテーマを `pull` する

ベースとしたいテーマをログインしたストアから `pull` します。
自分のプロジェクトディレクトリに移動し、フォルダを作成してから、`pull` します。
`your-theme-name` は、任意のフォルダ名に置き換えて実行してください。

```shell:Terminal
# プロジェクトディレクトリを作成して移動
$ mkdir your-theme-name && cd your-theme-name

# ストアからテーマをプル
$ shopify theme pull
```

複数のテーマがある場合は、以下のようにどのテーマをダウンロードするか選択できます。

```shell:Output
? Select a theme to pull from (Choose with ↑ ↓ ⏎, filter with 'f')
> 1. LIVE THEME [live]
  2. OTHER THEME [unpublished]
  3. ...
```

テーマを選択すると、ダウンロードが始まります。

```shell:Output
┏━━ Pulling theme files from LIVE THEME (#000000000000) on 〇〇.myshopify.com ━━━━━━━━━━━━━━
┃                                                                                      100%
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (66.1s) ━━
✓ Theme pulled successfully
```

## ローカルホストを立ち上げる

ローカルホストを立ち上げ、開発用のテーマを作成します。
以下のコマンドを実行しましょう。

```shell:Terminal
$ shopify theme serve
```

`shopify theme serve` コマンドを実行すると、ローカルのテーマのコードをもとにログインしたストアに開発テーマを作成できます。

「開発テーマ」とは、開発に使用している　Shopify　ストアに接続されている一時的な隠しテーマのことです。。
テーマを開発テーマとしてストアに接続すると、そのストアのデータをローカルテストに使用することができます。

開発テーマは Shopify ストアや開発ストアで使うことができます。
開発テーマはテーマの上限にはカウントされず、7日間使用されないとストアから削除されます。

serveが成功すると以下のような出力がされます。

```shell:Output
┏━━ Viewing theme… ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┃ * Syncing theme #000000000000 on 〇〇.myshopify.com
┃                                                               100%
┃ 
┃ Serving .
┃ 
┃ Please open this URL in your browser:
┃ http://127.0.0.1:9292
┃ 
┃ Customize this theme in the Online Store Editor:
┃ https://〇〇.myshopify.com/admin/themes/000000000000/editor
┃ 
┃ Share this theme preview:
┃ https://〇〇.myshopify.com/?preview_theme_id=000000000000
┃ 
┃ (Use Ctrl-C to stop)
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ (65.87s) ━━
```

shopify theme serveコマンドで、ローカルマシンにあるテーマを開発テーマとして、接続しているストアにアップロードして以下の情報を返します。

- 開発テーマへのリンク `http://127.0.0.1:9292` 。このURLは、CSSやセクションのローカルな変更をホットリロードするので、ストアのデータを使ってリアルタイムに変更をプレビューすることができる。このプレビューは、Google Chromeでのみ利用できる。
- 開発テーマのオンラインストアエディターへのリンク
- 他の開発者と共有できるプレビューリンク

基本的には、`http://127.0.0.1:9292` のリンクでホットリロードしながら開発し、ノーコードの編集が必要な際は `https://〇〇.myshopify.com.com/admin/themes/000000000000/editor` のURLにアクセスし適宜カスタマイズを行います。

## Git / GitHub の設定を行う

Tailwind CSS を組み込んだテーマは、GitHubと連携してストアにアップロードしますので、Git / GitHub との連携を行います。
あらかじめ GitHub でからのリモートリポジトリを作成しておきましょう。

以下のコマンドを実行していきます。

```shell:Terminal
# Git の初期化
$ git init

# 初回コミット
$ git add .
$ git commit -m 'first commit'

# リモートリポジトリの登録（`<リモートリポジトリのURL>`は先ほど作成したからのリポジトリのURL）
$ git remote add origin <リモートリポジトリのURL>

# 初回プッシュ
$ git push -u origin main
```

正常にプッシュされれば OK です。

## GitHub リポジトリをストアテーマに接続する

プッシュしたリポジトリのテーマをストアに接続します。
GitHubとの連携を行うと、常にストアのテーマの状態とGitHubリポジトリのテーマの状態が同期します。
つまり、ストアでノーコードのカスタマイズやアプリのインストールを行うと、それによって生じたコードの差分がGitHubにも同期されます。
逆にGitHubに新たに編集差分をマージすると、自動的にストアのテーマとも同期します。

![スクリーンショット 2021-07-11 15.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022930/ebc05221-47ab-6394-e922-89fd9b901e20.png)

アカウントとリポジトリとブランチを選択し接続します。
![スクリーンショット 2021-07-11 15.25.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022930/15dd14ef-9088-8f7d-a0f1-095dbf303aaa.png)

以下のように接続が完了したらOKです。

![スクリーンショット 2021-07-11 15.26.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022930/dc086534-bdf9-f106-c719-29caf76f17a2.png)

それでは、Tailwind CSS を導入していきましょう。

## `package.json` を生成する

`npm init` を実行して `package.json` を生成します。
開発を行うプロジェクトのディレクトリに移動して以下のコマンドを実行します。

```shell:Terminal
$ npm init -y
```

`-y` オプションは `npm init` で `package.json` を生成する際の全ての質問を `Yes` で生成するというものです。

以下のような `package.json` が生成されればOKです。

```json:package.json
{
  "name": "shopify-tailwind-test-2",
  "version": "1.0.0",
  "description": "[![Build status](https://github.com/shopify/dawn/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Shopify/dawn/actions/workflows/ci.yml?query=branch%3Amain) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?color=informational)](/CONTRIBUTING.md)",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
```

## Tailwind CSS のパッケージをインストールする

Tailwind CSS のパッケージを `npm install` します。パッケージは最新のものをインストールします。

```sehll:Terminal
$ npm install -D tailwindcss@latest
```

公式ドキュメントでは、postcss@latestとautoprefixer@latestも同時にインストールされています。
色々と検証・考察した結果、PostCSSのプラグインを使わない限りはtailwindcssのパッケージのみで良さそうという結論に至ったのでここではtailwindcss@latestのみインストールします。

`package.json` の `devDependencies` に以下のように追記されればOKです。

```diff_json:package.json
{
  "name": "shopify-tailwind-test-2",
  "version": "1.0.0",
  "description": "[![Build status](https://github.com/shopify/dawn/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Shopify/dawn/actions/workflows/ci.yml?query=branch%3Amain) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?color=informational)](/CONTRIBUTING.md)",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
- "license": "ISC"
+ "license": "ISC",
+ "devDependencies": {
+   "tailwindcss": "^2.2.8"
  }
}
```

## `tailwind.config.js` ファイルを作成する

Tailwind CSS の設定ファイルである `tailwind.config.js` を作成します。
以下のコマンドを実行してください。

```shell:Terminal
$ npx tailwindcss init
```

以下のような`tailwind.config.js`ファイルが作成されればOKです。

```js:tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

## JITモードを有効化する

Tailwind CSS v2.2から追加されたJIT（Just in Time）モードを有効化します。
`tailwind.config.js`ファイルに設定を追記します。

```diff_javascript:tailwind.config.js
module.exports = {
+ mode: "jit",
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

## パージの設定をする

パージの対象とするファイルを設定します。

```diff_javascript:tailwind.config.js
module.exports = {
  mode: "jit",
- purge: [],
+ purge: [
+   "./layout/*.liquid",
+   "./templates/*.{liquid, json}",
+   "./sections/*.liquid",
+   "./snippets/*.liquid",
+   "./assets/*.{liquid, js}",
+ ],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

`purge` の設定では、Tailwind CSS のクラスを書く可能性のあるファイル全てをしています。

## `prefix` を設定する

既存のテーマに Tailwind CSS を導入する場合は、`prefix` を設定します。

```diff_javascript:tailwind.config.js
module.exports = {
  mode: "jit",
+ prefix: "tw-"
  purge: [],
  purge: [
    "./layout/*.liquid",
    "./templates/*.{liquid, json}",
    "./sections/*.liquid",
    "./snippets/*.liquid",
    "./assets/*.{liquid, js}",
  ],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

上記の設定により、Tailwind CSS の全てのクラス名の先頭に `tw-` というプレフィックスがつきます。
`grid` や `flex` といったクラスは、既存のテーマでも使われいてる可能性が非常に高く、CSS のバッティングが起こってしまします。
プレフィックスの設定により、Tailwind CSS の`grid` というクラスが `tw-grid` となりますので、競合を防ぐことができます。

## Tailwind CSSの読み込みを行う

ビルドの元となる CSS ファイルを作成します。

```shell:Terminal
mkdir _css && touch _css/tailwind.css
```

`_css/tailwind.css` ファイルでは、`@tailwind` で Tailwind のモジュールから `base` や `utilities` を読み込みます。
以下のように記述しましょう。

```css:_css/tailwind.css
@tailwind components;
@tailwind utilities;
```

このファイルでは、`@layer`を使って `utilities` クラスの拡張などを設定することができます。
Tailwind CSS のビルド元をこのファイルに指定することで、カスタマイズした設定などを元にビルドを行ってくれます。

通常 Tailwind CSS を使用する際は、`@tailwind base;` という ベース CSS もインポートします。ですが、今回はあえてインポートしていません。
理由は、Tailwind CSS のベース CSS が、既存のテーマの CSS にも影響を与えてしまうからです。これにより、予期せぬ表崩れを防ぐことができます。

## `assets/tailwind.css`をビルドする

ここまで設定できたら一度 `assets` ディレクトリに Tailwind CSS のビルドファイルを作成します。
以下のコマンドを実行します。

```shell:Terminal
npx tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css
```

`assets` ディレクトリに `tailwind.css` ファイルがビルドされればOKです。
`-i ./_css/tailwind.css` の部分でビルドの元にするファイルを指定し、`-o ./assets/tailwind.css` でビルド先のファイルを指定します。
JIT モードを有効にしているので、この時点ではビルド後のファイルには何も記載されないと思います。


## `theme.liquid` で `assets/tailwind.css` を読み込む

ビルドした Tailwind CSS ファイルを `layout/theme.liquid` で読み込み、Tailwind のスタイリングを反映させます。
以下のコードを `layout/theme.liquid` の `<head> ... </head>` の中に追記します。

```liquid:layout/theme.liquid
<head>
  ...
  {{ "tailwind.css" | asset_url | stylesheet_tag }}
  ...
</head>
```

## npmスクリプトを作成する

毎回`tailwindcss`コマンドを叩くのは面倒なので、npmスクリプトとしてまとめます。
`package.json`の`scripts`を以下のように書き換えます。

```diff_json:package.json
{
  "name": "shopify-tailwind-test-2",
  "version": "1.0.0",
  "description": "[![Build status](https://github.com/shopify/dawn/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/Shopify/dawn/actions/workflows/ci.yml?query=branch%3Amain) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?color=informational)](/CONTRIBUTING.md)",
  "main": "index.js",
  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1"
+   "dev": "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css",
+   "dev:watch": "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css --watch",
+   "build": "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css --minify"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "tailwindcss": "^2.2.8"
  }
}
```

作成したコマンドについて解説します。

### `dev`コマンド

```shell:Terminal
$ npm run dev
# 実行されるのは "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css"
```

`npm run dev` コマンドで、シンプルな Tailwind のビルドを一度だけ行うことができます。
ビルドされたファイルは、圧縮されていないコードです。


### `dev:watch`コマンド

```shell:Terminal
$ npm run dev:watch
# 実行されるのは "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css --watch"
```

`npm run dev:watch` コマンドで、`tailwind.confit.js` の `purge` に設定したファイルを常に監視し、ファイル内で新しい Tailwind CSS のクラスが使われる度にビルドが走ります。JIT モードで開発を快適に行いたい場合はこの設定が必須です。
開発を行う際は `shopify theme serve` と、`npm run dev:watch` コマンドを同時に使用します。
VS Code のエクスプローラーの NPM スクリプトに `dev:watch` とあるので、再生マークをクリックすると新たにターミナルが立ち上がり npm スクリプトが実行されるため便利です。

> 参考記事

https://unblog.unreact.jp/blog/vscode-npm-scipts


### `build`コマンド

```shell:Terminal
$ npm run build
# 実行されるのは "tailwindcss -i ./_css/tailwind.css -o ./assets/tailwind.css --minify"
```

`npm run build` コマンドで、本番環境用の `assets/tailwind.css` ファイルをビルドします。`tailwindcss` コマンドの `--minify` オプションにより、ビルド後のコードが圧縮されます。（ 1 行に圧縮されたCSSファイルがビルドされます）

## Ignore ファイルを作成する

各種 Ignore ファイルを作成します。

### `.gitignore` ファイル

`.gitignore` ファイルを作成します。この `.gitignore` に書かれたファイルは Git の管理下から外されます。

```shell:Terminal
$ touch .gitignore
```

```:.gitignore
node_modules
```

### `.prettierignore` ファイル

普段 Prettier を使っている方は、Liquid ファイルが Prittier で整形されてしまわないように設定します。

```shell:Terminal
$ touch .prettierignore
```

```:.prettierignore
/**/*.liquid
```

### `.shopifyignore` ファイル

`.shopifyignore` は、Shopify CLI を使用して操作したくないファイルがテーマと同じリポジトリにある場合に使用します。
テーマに関するフォルダ以外を設定します。

```shell:Terminal
$ touch .shopifyignore
```

```:.shopifyignore
.gitignore
.prettierignore

package.json
package-lock.json

postcss.config.js
tailwind.config.js

_css/tailwind.css

README.md
```

# まとめ

Shopify テーマに Tailwind CSS を導入して快適なテーマカスタマイズを行っていきましょう！

最後まで読んでいただきありがとうございました。
ミスやご指摘ありましたら、コメントではなく、わかりやすい編集リクエストを送っていただけると幸いです。