一休.com Developers Blog

一休のエンジニア、デザイナー、ディレクターが情報を発信していきます

一休.comスマホサイトのパフォーマンス改善(CSS・その他細かいチューニング編)

こんにちは。 一休.comの開発基盤を担当しています、akasakasです。

今回は、一休.comスマートフォンホテルページリニューアルをリリースし、パフォーマンスが改善したお話をさせて頂きます。

概要編とJavaScriptパフォーマンス改善編はこちらになります。

user-first.ikyu.co.jp

user-first.ikyu.co.jp

この記事ではスマートフォンホテルページリニューアルで実施したCSS・その他細かいチューニングについてお話しします。

ここでお話しする内容

  • CSS再設計&チューニング編
    • リニューアル前のスマートフォンホテルページのCSSの現状整理と抱えていた課題
    • リニューアルをするにあたり、CSS再設計
      • CSS Modules
      • FLOCSS
    • パフォーマンス
      • インライン展開
      • 非同期読み込み
    • ドキュメント整備
  • その他細かいチューニング編
    • resource hints/preconnect
    • 画像の遅延ロード
    • imgix
  • まとめ
  • おまけ:こんなスタイルは嫌だ

CSS再設計&チューニング編

リニューアル前のスマートフォンホテルページのCSSの現状整理と抱えていた課題

リニューアル前のスマートフォンホテルページのCSSに関する課題は以下の点が大きな悩みでした。

  • 7,000行越えのメンテナンス困難なCSS
  • どのスタイルがどこで使われているか不明
  • いろんなところでいろんなCSSファイルが呼ばれている

7,000行越えのメンテナンス困難なCSS

上書きに上書きを重ねているので、メンテナンスが大変でした。

f:id:akasakas:20180902204612p:plain:w300

どのスタイルがどこで使われているか不明

ネストが深く、命名ルールもなかったので、どのスタイルがどこで使われているのかがわかりづらかったです。

.search_cont #rmsrch_frame_disp_main .rmsrch_frame_disp_row .pep_frame {
  width: 24%;
}

いろんなところでいろんなCSSファイルが呼ばれている

概要編でお話しましたが 一休.comのほとんどはVB.NETでシステムが構築されています。
ASP.NET Web Formsベースの独自フレームワークです。

プレゼンテーション層はMasterPageがあり、
それぞれの画面に対して、aspxファイルがあり、
また、細かい部品ごとに対して、ascxファイルがあります。

それぞれのファイルに対して、cssファイルが定義されていたため、
bodyタグの途中でCSSファイルが呼ばれているなんてこともありました。

レイアウトは下記のようなイメージです。

f:id:akasakas:20180910191958p:plain

一例ですが、
divタグ内でstylesheetが呼ばれているということもありました。

f:id:akasakas:20180907234134p:plain:w500

リニューアルをするにあたり、CSS再設計

リニューアルをするにあたり、上記の課題を解決し、パフォーマンス面の改善も図りました。
キーワードは以下になります。

CSS Modules

一休では Vue.js を採用しています。
Vue コンポーネントに関しては CSS Modules を積極的に採用しています。
CSS Modules を採用し、コンポーネントごとにスコープを切れば、どのスタイルがどこで使用されているかがわかりやすくなり、メンテナンス性が保証されると考えました。

FLOCSS

しかし、CSS Modules 以外でグローバルに影響を及ぼすCSSを書かなければいけないケースが発生します。
上記のケースについては別途対応が必要だと考えました。
こちらはFLOCSSを採用しました。
FLOCSSについてはこちらをご覧いただければ、わかると思います。

github.com

ディレクトリ構成は下記のようなイメージです。

├─app
│      sd_hotel.css
│
├─foundation
│      _base.css
│      _reset.css
│
├─layout
│      _footer.css
│      _header.css
│
└─object
    ├─component
    │      _component1.css
    │      _component2.css
    │
    ├─project
    │  │
    │  └─hotel
    │          _hotel_part1.css
    │          _hotel_part2.css
    │
    └─utility
            _utility1.css
            _utility2.css

CSS プリプロセッサにPostCSSを採用しました。
Foundation/Layout/Objectのcssファイルを統括するためのsd_hotel.cssがあるようなイメージです。
sd_hotel.cssはFoundation/Layout/Object内のcssファイルを適宜インポートしています。
ここはFLOCSSの基本的な考え方を採用しています。

@charset "utf-8";

/* ==========================================================================
// Foundation
==========================================================================*/

@import "../foundation/_reset.css";
@import "../foundation/_base.css";

/* ==========================================================================
// Layout
==========================================================================*/

@import "../layout/_header.css";
@import "../layout/_footer.css";

/* ==========================================================================
// Object
==========================================================================*/

/* ==========================================================================
// Component
==========================================================================*/

@import "../object/component/_component1.css";

/* ==========================================================================
// Project
==========================================================================*/

@import "../object/project/hotel/_hotel_part1.css";
@import "../object/project/hotel/_hotel_part2.css";

/* ==========================================================================
// Utility
==========================================================================*/

@import "../object/utility/_utility2.css";

パフォーマンス

CSSはレンダリングブロック対象になります。 レンダリングブロックはパフォーマンス低下に繋がるので、これを解消するために下記2点を気をつけました。

インライン展開

Above the Fold に入るスタイルはインライン展開することでレンダリングブロックを回避しました。
ただ、htmlファイルに直接、インライン展開したスタイルを書くとメンテナンス性を保証することはできません。

そこで、サーバサイド側で外部cssファイルを読み込んで、インライン展開するヘルパーメソッドを1つ用意しました。
これにより、外部ファイルで管理できて、かつインライン展開ができるので、メンテナンス性とパフォーマンスの向上を図ることができました。

非同期読み込み

Below the Fold になるスタイルはインライン展開せずに、loadCSS を使って、非同期で読み込むようにしました。

ドキュメント整備

今後の色んなエンジニア・デザイナーがメンテナンスするためにドキュメントを整備しました。 書いたこととしては

  • 設計方針
  • ディレクトリ構成
  • 命名ルール
  • パフォーマンス
  • アンチパターン

です。

f:id:akasakas:20180920185039p:plain:w500

その他細かいチューニング編

resource hints/preconnect

サードパーティドメインに対してはpreconnectを指定して、あらかじめDNSの名前解決に加え、TCPコネクションまで貼っています。

画像の遅延ロード

Below the Fold の部分の画像は初回リクエストに含めず、遅延ロードさせてます。
一休では画像の遅延ロードにlazysizesを使っています。

github.com

imgix

imgixの導入で画像最適化ができたので、パフォーマンス改善に大きく寄与しました。
imgixについての記事はこちらをご覧頂ければと思います。

user-first.ikyu.co.jp

まとめ

今回は、一休.comスマートフォンホテルページリニューアルをリリースし、パフォーマンスが改善したお話をさせて頂きました。
その中でも、CSS・その他細かいチューニングについてお話させて頂きました。

リニューアル前には下記の課題がありましたが、

  • 7,000行越えのメンテナンス困難なCSS
  • どのスタイルがどこで使われているか不明
  • いろんなところでいろんなCSSファイルが呼ばれている

上記の課題に対して

  • CSS Modules/FLOCSS を採用し、メンテナンス性を担保
  • インライン展開/loadCSSを使った非同期読み込みでパフォーマンス改善

今後はこれをスマートフォンホテルページだけでなく、他のページにも展開して行き、ユーザに高い価値を提供していきたいと思います。

おまけ:こんなスタイルは嫌だ

CSS再設計をしている途中で見つけたリプレイス前の残念スタイル集を少しだけお見せします。
過去から学び、今後に活かしていきたいです。

HTMLに直接書いている

<span style="font-size:13px; font-weight:normal;"> 

ネストが深すぎる、HTML側のDOM修正時に影響を受けやすい

#sdGuidePage .figureimg-list-roomlist .shisetu_box.guide_top_photo .photoTop img,#sdGuidePage .figureimg-list-roomlist .shisetu_box.guide_top_photo .photoNext img,#sdGuidePage .figureimg-list-roomlist .shisetu_box.guide_top_photo .photoPrev img {
  height: 24px;
}

同じ内容

.mt10 {
    margin-top: 10px;
}

.top_m_10px {
    margin-top: 10px;
}

CSSエンジニア募集

一休ではユーザに高い価値を提供することができるCSSエンジニアを募集しています!

hrmos.co

参考資料