続:futureshop(フューチャーショップ)を使用する際の開発環境の設計(2016)

2014年に公開した 「FutureShop2(フューチャーショップ2)を使用する際の開発環境の設計」 という記事をたくさん見ていただいているようで、Googleで「FutureShop2」「フューチャーショップ2」と検索すると本家さんの下(2番目)に表示されるまで評価してもらっているのですが、結構古い上に当時の特殊な環境を前提とした内容になっているので、もっと一般的な場合を想定して、もう一度ベストプラクティスを考えてみました。こちらの方がより多くの方にフィットすると思うので、参考にしていただけるとうれしいです。

次のようなケースを想定しています。

  • 新規に構築する(リニューアル前のファイル構造を引き継がなくて良い)
  • 開発やテストサーバには、SSL用の環境がない

前回の記事 は「既に存在するサイトを引き継いで一部リニューアルする」という状況だったので、不必要にややこしくなっていました。

考慮すべきFutureShop2の仕様

これは前回のおさらいで、注意すべき点は変わっていません。特筆すべきは、下図のように1つのサイトに対して最低でも3つドメインが発生することと、更新手段がFTPと管理画面からのアップに分かれる点です。

特殊なFutureShop2の仕様

ページ例 ドメイン例 設置手段
オンラインショップのトップページ http://www.example.com FTP(1)でアップ
お問い合わせフォーム https://secure*.future-shop.jp/~{店舗ID}/ FTP(2)でアップ
商品詳細ページ http://www.example.com/fs/{店舗ID}/ 管理画面から登録
カート以降のページ https://**.future-shop.jp/fs/{店舗ID}/ 管理画面から登録

お問い合わせフォームを共用SSLに設置する場合は合計3つドメインが発生し、さらに「オンラインショップのトップページ」と「商品詳細ページ」はドメインは同じでもファイルが設置されるサーバ領域は別の場所、という複雑な構成です。

 何が問題か

上図のような複数のドメインやサーバ領域が存在する案件でよく検討せずに作ると、開発→テストアップ→本番の各ステップで、CSSやJS、時には画像のパスまでも変えなければいけなかったり、ほぼ同じ内容のCSSファイルがあっちとこっちに存在したり、画像の修正をしたけどSSLのページで使われてる画像は実は変わってなかったり…という何ともメンテナビリティの悪い状態が簡単に発生してしまいます。

このような状態を未然に防ぎ、属人的な「個別案件あるある」に頼った運用にならないために、クリアすべきポイントは次です。

  • 開発→テスト→本番の各ステップにおいて、パスの変更を極力行わずに済む方法を考える。
  • 特に画像のパスは変更しなくて済むように。(影響範囲が果てしないため)
  • 画像の重複管理は避ける。(あっちもこっちも更新、ということがないように)
  • サイトに共通するCSS、JSは一元管理する。(〃)

FutureShop2での具体的な課題

「商品ページは非SSL、カート以降はSSL。でもヘッダーとかフッターで同じ画像使うし、CSSだって共通で使いたい」というのは当然の思い。この要件を満たすための機能(仕様)がFutureShop2には用意されています。

CSSやJavaScriptファイルの仕様

ショップシステムにより動的に出力されるページ(商品カテゴリページや商品ページ)に読み込まれるCSSやJSファイルについては、次のような仕様があります。

  • CSSとJSはファイルをFTPでアップするのではなく、管理画面から内容を登録する。
  • それらの設置先パスは、CSSの場合/shop/item/{店舗ID}/design/template01/css/original.cssとなり、JSの場合/shop/item/{店舗ID}/design/template01/css/original.jsとなる。
  • 上記2つのファイルは、商品ページなどの非SSL領域でも、カート以降のSSL領域でも同じものが読み込まれる

画像ファイルの仕様

商品画像や商品のカテゴリ画像など、カートシステムと連動する画像ファイルについては、必ず管理画面から登録する必要があります。

  • 商品画像や商品のカテゴリ画像など、カートシステムと連動する画像ファイルはFTPでアップせず、管理画面から登録する。
  • 登録した画像の設置ディレクトリは/shop/item/{店舗ID}/design/img01/(~/img05/)となる。
  • これらの画像は、商品ページなどの非SSL領域でも、カート以降のSSL領域でも同じものが読み込まれる

このように、管理画面でCSSやJSのコードを登録したり画像をアップする ことで、商品ページ(非SSL)でもカート以降(SSL)でも同じ画像やCSS, JSを使うことが出来るようになっています。なんとすばらしい!

…でもこれ、本番環境だけだと問題ないですが、サイトの構築中や運用時のテストサーバでは当然同じようには行かない わけで。逆に言うと、本番環境では上記のようなパス構造になるということを念頭に、開発・テスト環境を設計する必要があるということになるのです。

ベストプラクティスなディレクトリ構造

では実際どうしたらいいのか。ですが、説明が難しくなりそうなので先に結論を。
店舗IDを仮にgranfairsとして、現時点で一番おすすめなディレクトリ・ファイル構造が次です。

ディレクトリ構造1

※静的ページがトップページのみのシンプルなサイトを例としています。

ディレクトリ 用途 本番でのURL
~granfairs 共用SSL用 https://secure*.future-shop.jp/~{店舗ID}/
fs 商品カテゴリ/詳細ページ用 http://www.example.com/fs/
shop 管理画面で登録するファイル用 /shop/item/{店舗ID}/design/
index.html トップページ http://www.example.com/index.html

/~granfairs/は共用SSLの領域に割り当てられる/{~店舗ID}/ディレクトリです。このディレクトリ自体はアップせず、この配下のディレクトリ・ファイルを共用SSLサーバにアップします。

/fs//shop/はFutureShop2において本番サーバへのアップや作成が許可されていない、システムで予約されているディレクトリ名です。 これらは本番にアップするためのディレクトリではなく、開発やテスト時に本番と同じ環境を再現するために使用します。

基本ルール

  • ファイルへのパスは「/」始まりの絶対パスで記述する
  • 非SSLと共用SSL用のHTMLファイルは別で管理する

これを前提に、以下それぞれのディレクトリの役割とルールを考察します。

CSS, JSファイルの管理方法

CSSやJSは、SSL環境下でも参照されることが前提です。なので「共用SSL配下にファイルを置いて、管理画面での登録はしない」という方法が浮かびます。共用SSL用のディレクトリは/~{店舗ID}/なので、次のような感じ。

ディレクトリ構造2

この場合、トップページなどの静的HTMLからCSS, JSファイルを直接参照すると記述は次のようになります。(簡易にするためreltype属性を省いています)

<link href="/~{店舗ID}/assets/css/global.css" />
<script src="/~{店舗ID}/assets/js/common.js"></script>

ただこうなると、開発中やテストサーバではOKですが、本番サーバではパスをURLに書き換えないといけません。(共用SSLはドメインが別なので)

<link href="https://secure*.future-shop.jp/~{店舗ID}/assets/css/global.css" />
<script src="https://secure*.future-shop.jp/~{店舗ID}/assets/js/common.js"></script>

運用時も、テストアップの都度パスを元の状態に変更する必要があり、メンテナビリティがいいとは言えません。さらに、商品カテゴリページや商品詳細ページでは<head>内にこの記述をすることができないので、静的ページとシステム出力ページで管理方法が変わってしまうのも難点です。

本番と同じディレクトリ・ファイルを作る

そこで、ファイルへの参照パスを書き換えなくて良いように、本番と同じディレクトリ構造を作ってしまいます。

本番サーバでのパスは、CSSの場合/shop/item/{店舗ID}/design/template01/css/original.css、JSの場合/shop/item/{店舗ID}/design/template01/js/original.jsなので、次のようになります。

ディレクトリ構造3

静的ページの<head>の記述は次になります。(簡易にするためreltype属性を省いています)

<link href="/shop/item/{店舗ID}/design/template01/css/original.css" />
<script src="/shop/item/{店舗ID}/design/template01/js/original.js"></script>

これで、開発・テスト時も本番時もパスを変更する必要がなくなりました。

そうなるとこのファイルに直接コードを記述すると良さそうですが、その場合、本番に反映する際には、追加変更したコードをコピーして管理画面から登録するという手順が必要になってしまいます。そこにヒューマンエラーが発生しそうなので、original.css/js には直接コードを記述しません。

original.css/js で共用SSLのファイルを読み込む

これを回避するため、開発・テストサーバで作成したoriginal.css/jsファイルには、共用SSL配下に設置したCSS/JSファイルを読み込む記述をします。(簡易にするためreltype属性を省いています)

/shop/item/{店舗ID}/design/template01/css/original.css

@import "/~{店舗ID}/assets/css/global.css";

/shop/item/{店舗ID}/design/template01/js/original.js

document.write('
  <script src="/~{店舗ID}/assets/js/vendor/jquery-1.11.3.min.js"></script>
  <script src="/~{店舗ID}/assets/js/common.js"></script>
');

そして、FutureShop2の管理画面には次のように登録します。

管理画面

大事なのは、開発・テスト用のoriginal.css,original.jsはパスを「/」始まりで指定し、本番用に管理画面で登録するパスはhttpsで始まる共用SSLのURLを指定 している点です。

開発・テスト時と本番時のファイルの位置関係は次のようになります。

テスト時と本番時のファイルの位置関係

これで、

  • 開発・テスト・本番のステップに関わらず、また静的ページ・システムページの別なく、HTML内のパスを書き換えることなく、
  • 本番と完全に独立してテストが実行でき、
  • テストでOKであれば、作業したCSS/JSファイルを共用サーバにアップするだけ

というシンプルなフローになり、メンテナンスしやすい状態になりました。

画像ファイルの管理方法

続いて、画像の設置場所について考察します。画像についても、非SSL(http)/SSL(https)両方で参照される可能性があるので、SSL領域に設置します。その場合選択肢として次の2つが考えられます。

  1. 共用SSLサーバに設置する(すなわち/~granfairs/配下に設置する)
  2. 管理画面から登録する想定で/shop/item/~配下に設置する

ただし、どちらか一方ではNG。

仮に共用SSLサーバに全ての画像を設置した場合、本番時には<img src="" />で呼び出される画像のパスを全てhttps://~から始まるURLで指定しなければなりません。 もう一方、全てを管理画面から登録する想定で/shop/item/~に設置した場合、CSSファイル内で呼び出される画像のパスが本番時に通らなくなります。 (CSSファイル自体が共用SSLにあるため、CSSファイル内で呼び出す画像は、共用SSLに置かないとパスが通らないのです。)

よって、画像の設置ルールは次になります。

  • 表面画像(<img src="" />で指定する画像)は管理画面から登録する想定で/shop/item/~配下に置く
  • 背景画像などCSSファイルで呼び出す画像は、共用SSLに設置する=/~granfairs/配下に置く

画像の設置場所

このようなルールにしておくと、HTMLやCSSにて呼び出すときのパスは一律「/」始まりでOK。開発から本番までのステップでも、パスを書き換える必要がありません。

HTMLにて画像を参照

<img src="/shop/item/{店舗ID}/design/img01/hoge.png" />

CSSにて画像を参照

.hoge {
  background: url(/~{店舗ID}/assets/img/common/bg-01.jpg);
}

開発・テスト時もパスが通り、本番時にページが非SSL(http)/SSL(https)どちらで参照されてもセキュリティーエラーにはならず正しく表示されます。

これで難しい部分の設計は完了です!

商品カテゴリ/商品詳細ページ

商品カテゴリページや商品詳細ページは、FutureShop2の管理画面で言う「上級デザイン」にオリジナルのHTMLを登録して、コンテンツをリッチに仕上げることがほとんどだと思います。

その「上級デザイン」に登録するためのHTMLを作成してテスト確認するために/fs/ディレクトリを使用します。登録する商品のカテゴリや詳細ページのURLコードに合わせて、次のようにディレクトリを構成してindex.htmlを設置。これを商品カテゴリページや商品詳細ページに見立てて、「上級デザイン」に登録するHTMLを作成します。

商品カテゴリや商品詳細ページ

こうしておくと、本番時と同じリンク構造になるので、静的ページから商品カテゴリページに仮にリンクさせたい場合でも予めパスを通しておくことができ確認がスムーズです。

本番時、商品カテゴリや商品詳細ページのURLの末尾には「/」が付きません。
例)/fs/{店舗ID}/c/hoge(※1)
なので開発・テスト時も最後の「/」を付けないようにしましょう(※2)。

※1:FutureShop2では、末尾に「/」を付けてもちゃんと表示されます。ただしURLの「正規化」という面で、発リンクは「/」なしに統一した方がベターだと考えます。

※2:サーバによっては末尾「/」がないと正常にパスが届かない場合がありますが、その際は.htaccessとかで「/」を補完するように設定すれば良いと思います。

おまけ

この記事の例のようなシンプルな構成ではありませんが、同じ設計でリリースしたサイトをご紹介します。

格之進 一関と東京を食で繋ぐ(http://kakunosh.in/)

ここはオンラインストアをサイトの一部に内包する形になっているので、グランドトップ(上記URL)を始めほとんどのコンテンツにショップシステムは絡んでいませんが、オンラインストアを含めたサイト全体を通して、共通のCSS/JS/画像ファイルで管理しており、メンテナンスがしやすい状態になっています。

FutureShop2のカートを使ったオンラインストアの入り口は次になります。

格之進オンラインストア(http://kakunosh.in/store/)

去年の10月末に、3万円分を会社でお取り寄せしてメンバー全員でBBQしました!お肉、ほんとにおいしいので良かったらついでにポチッとw。