こんにちわ、@t32kだよ!
私は仕事では主にHTML/CSSコーディングを担当しているのですが、自分の書いたCSSがイケてるのか、そうでないのか、気になります。私、気になります!そうでなくても、他プロジェクトのCSSのレビューをお願いされたりすることもあるので、そのCSSがどのような状態であるのか、すばやく簡単に理解する必要性がありました。
そこで私は、StyleStatsというNode.js製のツールを作りました。
StyleStatsの使い方はとても簡単です。ターミナルから下記コマンドを打てば、すぐにCSSを解析した結果が得られます。
$ npm install -g stylestats
$ stylestats http://t32k.me/static/blog/skelton.css
stylestatsの引数に調べたいCSSファイルのパス(複数ファイル、リモートファイル対応)を入力すれば解析してくれます。
解析結果:
StyleStats!
┌─────────────────────────────────┬──────────────────────┐
│ Stylesheets │ 1 │
├─────────────────────────────────┼──────────────────────┤
│ Size │ 15.1KB │
├─────────────────────────────────┼──────────────────────┤
│ Rules │ 207 │
├─────────────────────────────────┼──────────────────────┤
│ Selectors │ 424 │
├─────────────────────────────────┼──────────────────────┤
│ Simplicity │ 48.82% │
├─────────────────────────────────┼──────────────────────┤
│ Most Identifers │ 4 │
├─────────────────────────────────┼──────────────────────┤
│ Most Identifers Selector │ nav ul li a │
├─────────────────────────────────┼──────────────────────┤
│ Lowest Cohesion │ 24 │
├─────────────────────────────────┼──────────────────────┤
│ Lowest Cohesion Selector │ a.button │
├─────────────────────────────────┼──────────────────────┤
│ Total Unique Font Sizes │ 15 │
├─────────────────────────────────┼──────────────────────┤
│ Unique Font Size │ 10px │
│ │ 11px │
├─────────────────────────────────┼──────────────────────┤
│ Total Unique Colors │ 11 │
├─────────────────────────────────┼──────────────────────┤
│ Unique Color │ #000 │
│ │ #777 │
├─────────────────────────────────┼──────────────────────┤
│ Id Selectors │ 14 │
├─────────────────────────────────┼──────────────────────┤
│ Universal Selectors │ 0 │
├─────────────────────────────────┼──────────────────────┤
│ Unqualified Attribute Selectors │ 7 │
├─────────────────────────────────┼──────────────────────┤
│ Javascript Specific Selectors │ 0 │
├─────────────────────────────────┼──────────────────────┤
│ Important Keywords │ 6 │
├─────────────────────────────────┼──────────────────────┤
│ Float Properties │ 4 │
├─────────────────────────────────┼──────────────────────┤
│ Media Queries │ 8 │
├─────────────────────────────────┼──────────────────────┤
│ Properties Count │ width: 53 │
│ │ padding-left: 32 │
└─────────────────────────────────┴──────────────────────┘
なぜCSSを解析する必要があるのか?
単純にCSSを記述することは非常に簡単です。スタイルを当てたいターゲットをセレクタで表現し、そのブロックの中にプロパティと値を宣言していくだけです。
この方法は閲覧するだけのドキュメントをスタイル付けするのには問題はなかったでしょう。しかし、現在、私たちが作っているWebサイトというのは単純に読むだけのドキュメントというよりかは、アプリケーションに近い性質があります。アプリケーションというのはユーザーがしてほしいタスクを実行するもので状態変化などを伴いますし、デスクトップアプリケーションを見れば分かる通り、ボタンのような多種多様なUIコンポーネントを必要とします。また、Webアプリケーションはひっきりなしにリニューアルされ、UIコンポーネントを修正したり、削除したり、追加する必要性があります。
Webアプリケーションを実現するために、従来のドキュメント型のサイトを構築してきたようなCSSの記述の仕方をしていれば、すぐさまCSSはスパゲッティ化することでしょう。そこで私たちは、CSSを書く上でのベストプラクティスを理解しなければなりません。
基本的にはJSHintのように、CSSにもCSS Lintがあるので、こういったツールを使えばよいと思います。StyleStatsで出力される指標は、CSS Lintで指摘される項目を参考にしたものなので、StyleStatsを実行することで、そのベストプラクティスから自分のコードがどれだけ適応しているのか確認することができます。
CSSは基本的にUIに責任を持っているため、JavaScriptのように致命的なエラーになることが少ないかと思います。しかし、これがやっかいな問題だと思います。なんとなく使っていないコードが残っていたり、なんとなく非効率なセレクターを書いてたりして、問題が顕在化したときに対処しようと思っても、スパゲッティすぎてどうすることもできない(Command+A Delete!)ということがあります。
そうならないためにも、日々のコード品質チェックは欠かせないものと思います。
JavaScriptにPlatoという解析ツールがあるのですが、ちょうどこれのCSS版となれるよう今後ともStyleStatsを開発していくつもりです。
各種指標の意味
単純にファイルサイズだけを見ていても、そのCSSが良いCSSなのか悪いCSSなのかよく分かりませんので、その他にもCSS Lintをベースとした指標があります。
$ stylestats -c path/to/.stylestatsrc
のように、.stylestatsrc
といった設定JSONファイルを一緒に読み込むことで、指標の表示・非表示などカスタマイズできます。
今回解説する指標はv2.2.1時での指標となります。今後、変更や追加などが想定されますので、留意しておいてください。
Stylesheets
stylesheets
: boolean
解析するスタイルシートの数。下記のように3つのファイルを解析すれば、この値は3になります。
$ stylestats path/to/foo.css path/to/bar.css path/to/baz.css
Size
"stylesheets": true
解析するスタイルシートのファイルサイズです。複数読み込んだ場合は、合計値となります(以後の指標に関しても同じ)。
Data Uri Size と Raito Of Data Uri Size
"dataUriSize": true, "raitoOfDataUriSize": true,
スタイルシート内のインライン画像のサイズとスタイルシートに対する割合です。画像をインライン画像にすることでHTTPリクエストを抑えることができますが、外部CSSファイルがダウンロードされないとレンダリングが始まらないので、この数値が大きすぎるのもよくありません。
Gzipped Size
"gzippedSize": false
解析するスタイルシートのgzip後のファイルサイズです。処理が重いのでデフォルトでは、OFF(false
)にしてあります。
Rules
"rules": true
ルール(宣言ブロック)の数です(上図参照)。
Selectors
"selectors": true
セレクタの数です(上図参照)。
Simplicity
"simplicity": true
Rules / Selectors をパーセンテージで表したものです。これは個人的に追加した指標なのですが、Sassの@extend
などで継承していると下記のような状態になったりします。もちろんこれはバッドプラクティス的な継承の使い方かと思います。
このようにならないためにも、1つのルールには1つのセレクタが対応しているほうが、シンプルで都合がよいかとおもいます。
Most Identifers と Most Identifers Selector
"mostIdentifers": true, "mostIdentifersSelector": true
セレクタの中で最も識別子が多いセレクタとその数を表示します。
.foo .bar .baz { color: red; }
上記のセレクタの識別子は、3つとなります。これもSassのネストのような機能を使っていると、深くなる傾向がありますので、気をつけてください。
Lowest Cohesion と Lowest Cohesion Selector
"lowestCohesion": true, "lowestCohesionSelector": true
cohesionは凝集度のことです。凝集度に関してはWikipediaを参照。
凝集度(ぎょうしゅうど、コヒージョン、cohesion)とは、情報工学においてモジュール内のソースコードが特定の機能を提供すべく如何に協調しているかを表す度合いである。IPAが実施する情報処理技術者試験では、強度(きょうど、ストレングス、strength)という言葉が使われる。凝集度は順序尺度の一種であり、「凝集度が高い」とか「凝集度が低い」といった言い方で使われる。凝集度の高いモジュールは、堅牢性、信頼性、再利用性、読みやすさなどの点で好ましく、凝集度の低いモジュールは保守/評価/再利用/読解が難しいため、好ましくないとされる。
Lowest Cohesionは、SOLID CSSのSingle Responsibility Principle / 単一責任の原則に由来していて、一つのルールにあまりいろいろなスタイルを詰め過ぎないほうがよいです。そこで、Lowest Cohesionは各ルール内で一番宣言数が多いルールのセレクタと宣言数を表します。
Total Unique Font Sizes と Unique Font Size
"totalUniqueFontSizes": true, "uniqueFontSize": true
ユニークなフォントサイズとその数です。現状、font-size
プロパティで宣言されている値をとっています。font
プロパティによるショートカットで宣言されている値を取得できていません。
Total Unique Colors と Unique Color
"totalUniqueColors": true, "uniqueColor": true
ユニークなカラーとその数です、現状、color
プロパティで宣言されている値を取得しています。background-color
、border-color
などの値を含むかは検討中です。
ID Selectors
"idSelectors": true
IDセレクタを含むセレクタの数です。
Universal Selectors
"universalSelectors": true
ユニバーサルセレクタを含むセレクタの数です。
Unqualified Attribute Selectors
"unqualifiedAttributeSelectors": true
不適切な属性セレクタの数です。
.selected [type=text] {
color: red;
}
上記はこれに該当しますが、下記は該当しません。なぜならセレクタは右から左へと解析されるので、上記のセレクタの場合すべての要素をチェックするからです。
.selected [type=text] a {
color: red;
}
Javascript Specific Selectors
"javascriptSpecificSelectors": /[#\.]js\-/g
js-*
のようなJavaScript専用のセレクタを含む数です。DOMをJavaScriptから操作する場合、id属性やclass属性をフックとして利用します。これらの属性値にはjs-*
のような接頭辞をつけて、JavaScript専用のものとし、これらのセレクタにはスタイルを付与しないほうが、独立性を保てます。
デフォルトの接頭辞にはjs-*
を指定していますが、任意の正規表現オブジェクトを渡すことで変更可能です。
参考:
Important Keywords
"importantKeywords": true
!important
の宣言数です。
Float Properties
"floatProperties": true
float
プロパティの宣言数です。あれこれfloatしてレイアウトをこねくり回すより、最初からグリッドフレームワークの導入を考えたほうが得策な場合もあります。
Media Queries
"mediaQueries": true
Media Queriesの宣言数です。
Properties Count
"propertiesCount": 10
どのプロパティがどれだけ宣言されているのか、デフォルトではTop10までランキング出力してくれます。大体のCSSの傾向というか、見れて楽しいです。全部見たかったら、{"propertiesCount": 1000}
といった風に指定すればよいです。個人的にこれが欲しかったので作ったという背景もあります。
v2.2.1では以上の指標ですが、こういった指標があったら便利だなとか、この指標はこうしたほうがよいなどありましたら、どんどんIssuesをあげてください。よろしくお願いします。
CIツールとの統合
stylestats path/to/stylesheet.css -t csv
という風にすればCSV形式で出力できるので、これを使ってJenkins CI上でファイルサイズの変遷など記録したいと思います。
CloudBees社のサービスを使えば、月100分までのビルドが無料でJenkinsをクラウド上で利用できるので、それで試すのもよいかと思います。
Jenkins上で、グラフを作るためにPlot Pluginをインストールします。このプラグインは、Java properties、CSV、XMLにファイルを読み込みんでグラフを生成してくれます。
あとは、NodeJS Pluginなどで、Node.jsとStyleStatsをインストールすれば準備完了です。
ビルドの処理にStyleStatsを実行し、CSVで出力し、ビルド後の処理でそのCSVを読み込んであげれば、完了です。
あとは、GitHubと連携してレポジトリにコミットしたら、ビルドを実行させるなどトリガを設定してもらえればと思います。
File Size:
Style Info:
あとはデータが貯まると、こんなかんじでグラフが生成されます。CSSのリファクタリングは地道な作業ですので、ファイルサイズだけでなく、セレクタ数やルール数など細かい指標の変遷をチェックしていれば、モチベーションも持続できるかと思います。ぜひとも、導入してみてください。
また、ローカルで確認したい場合はGrunt/Gulpプラグインもありますので、そちらを使ってもらえるとよいです。
今後はtestspecファイルを認識できるようにし、例えばImpotant Keywordsが10個以上だったらテストを失敗させるといったことを、Jenkins・Travis-CIなどでできるようにしたいと思っています。
みなさんもぜひ使ってみてくださいね!
[追記] 2014年4月4日
オンラインでStyleStatsを使えるツールを公開しました。