この記事では、CSS ファイルと JavaScript ファイルのスペース使用量を最適化することで、より高いパフォーマンスを実現する方法を説明します。この 2 つの一般的なリソースは、コミュニティが提供するツールを使用して簡単に最適化できます。ただし、続行する前に、CSS ファイルと JavaScript ファイルの圧縮は、Web アプリケーションを「軽量」にするために使用できる多くの手法のうちの 2 つにすぎないことに注意することが重要です。他のリソース (HTML や画像など) を最適化する手法については、「リソース」を参照してください。
この記事を最大限に活用するには、次のツールをインストールする必要があります:
テキストエディタ
Java™ ランタイム環境 1.4 以降
問題: 空白のコンテンツ
開発者が CSS または JavaScript ファイルを操作する場合、通常は空白を使用するのが良いことです。ホワイトスペースには、ファイルのインデントに使用される文字、読みやすさを高めるためのスペース、記事の異なる部分を視覚的に区切るために挿入される追加の空白行が含まれます。空白があると、ファイルの読み取りと管理が容易になります。リスト 2 の CSS ファイルについて考えてみましょう。このファイルには、開発者が CSS コードの意図を理解できるように、適切な量の空白 (およびコメント) が含まれています。
現時点では、ファイルは将来変更される可能性が高いため、問題の長期的な解決策としてファイルを小さくすることは現実的ではありません。すべての空白と登録を削除すると、CSS と JavaScript コードが読みにくくなります。
問題は、空白スペースが増えるとファイルが大きくなり続けることです。各空白行、インデント、および括弧間のスペースは、CSS または JavaScript コードを適切に解析するために実際には必要のない、少なくとも 1 つの余分な文字を占めます。まず、1 つや 2 つの空白は大したことではありませんが、小さな金額が大きな倍数に乗算されると非常に大きな金額になります。
合計 5KB の余分な空白があるファイルについて考えてみましょう。 Web サイトが 1 日あたり 1,000 件のヒットを受信した場合、1 日あたり 5 KB を節約すると、1 か月あたり約 146 MB を節約できます ((5K * 1000 * 30) / 1024、概算値)。この点に関して、このドキュメントのクリック数はまだ比較的控えめな見積もりであり、実際の空白コストは増加する可能性があります。
さらに、ファイルをダウンロードするユーザーは、ファイルがダウンロードされるまで待つ必要があります。多くのユーザーがサイトへの最初の訪問後に CSS または JavaScript ファイルをキャッシュしたとしても、パフォーマンスは依然として最初の訪問に悪影響を与える可能性があります。 CSS ファイルと JavaScript ファイルを一度に 1 KB まで減らすことができれば、ブラウザーが読み込む必要がある数キロバイトのデータを削減できます。
解決策: 圧縮
この問題を解決し、少ないリソースを活用するには、CSS ファイルや JavaScript ファイルからコメントや空白などの余分な要素を削除するのが明白な解決策です。ただし、開発中にファイルからコメントや空白を削除することは現実的ではないため、より良い解決策は、Web サイトのリソースを「グレード」し、最適化してから公開することです。
空白文字を削除するカスタム スクリプトを作成することは、最初は実行可能な解決策のように思えますが、CSS および JavaScript ファイル自体にはかなりの空白が含まれています。したがって、空白を削除してファイルを圧縮するツールは、どの言語でどの空白が重要であるかを区別できるほど賢くなければなりません。
幸いなことに、そのようなツールはすでにコミュニティで利用可能であり、CSS や JavaScript ファイルなどのリソースの圧縮についてテストされています。そのようなツールの 1 つが YUI Compressor で、Yahoo!® Developer Network から入手できるツールです (リンクについては「参考文献」を参照)。
YUI コンプレッサー
YUI Compressor は Java で書かれたプログラムであり、Berkeley Software Distribution ライセンスに基づいてライセンスされています。 YUI Compressor は CSS および JavaScript コードを縮小 (圧縮) できるため、独自のツールを作成しなくても、リソースが小さくなる利点を享受できます。
YUI Compressor をダウンロードし、ファイルを解凍して、簡単にアクセスできる場所に置きます。アーカイブには、完全なソース コードと、YUI Compressor を構築するための Apache Ant スクリプト (build.xml) が含まれています。ただし、このファイルをビルドしたくない場合は、yuicompressor-{version}.jar をビルド ディレクトリに見つけることができます (図 1 を参照)。
図 1. アーカイブ ファイル ディレクトリ
YUI Compressor の JAR ファイルが付属しています。次のコマンドを入力して、ファイルを別のプロジェクトにコピーして実行できます。
<ol class="dp-xml"><li class="alt"><span><span>java -jar yuicompressor-2.4.2.jar --help </span></span></li></ol>
チェックリスト 1. YUI Compressor を Maven または IVY に追加する
<ol class="dp-xml"> <li class="alt"><span><span class="tag"><</span><span class="tag-name">dependency</span><span class="tag">></span><span> </span></span></li> <li><span> <span class="tag"><</span><span class="tag-name">groupId</span><span class="tag">></span><span>com.yahoo.platform.yui</span><span class="tag"></</span><span class="tag-name">groupId</span><span class="tag">></span><span> </span></span></li> <li class="alt"><span> <span class="tag"><</span><span class="tag-name">artifactId</span><span class="tag">></span><span>yuicompressor</span><span class="tag"></</span><span class="tag-name">artifactId</span><span class="tag">></span><span> </span></span></li> <li><span> <span class="tag"><</span><span class="tag-name">version</span><span class="tag">></span><span>2.3.6</span><span class="tag"></</span><span class="tag-name">version</span><span class="tag">></span><span> </span></span></li> <li class="alt"><span><span class="tag"></</span><span class="tag-name">dependency</span><span class="tag">></span><span> </span></span></li> </ol>
圧縮CSS
清单 2 是一个为便于开发人员维护而优化的 CSS 示例,它包含注释,且被用空白格式化了。
清单 2. 为维护而优化的 CSS 文件
<ol class="dp-css"> <li class="alt"><span><span class="comment">/* The main body for the page. */</span><span> </span></span></li> <li><span>body </span></li> <li class="alt"><span>{ </span></li> <li><span> font-family : <span class="value">Tahoma</span><span>,Geneva,</span><span class="value">sans-serif</span><span>; </span></span></li> <li class="alt"><span> background-color : <span class="value">#e2e2e2</span><span>; </span></span></li> <li><span> margin : <span class="value">0 0</span><span> </span><span class="value">0 0</span><span>; </span></span></li> <li class="alt"><span> padding : <span class="value">0 0</span><span> </span><span class="value">0 0</span><span>; </span></span></li> <li><span>} </span></li> <li class="alt"><span> </span></li> <li><span><span class="comment">/* The header and header elements */</span><span> </span></span></li> <li class="alt"><span><span class="value">#header</span><span>, </span><span class="value">#conten</span><span>t, </span><span class="value">#footer</span><span> </span></span></li> <li><span>{ </span></li> <li class="alt"><span> padding <span class="value">0</span><span>; </span></span></li> <li><span> margin <span class="value">0</span><span>; </span></span></li> <li class="alt"><span> width : <span class="value">100%</span><span>; </span></span></li> <li><span> min-width : <span class="value">600px</span><span>; </span></span></li> <li class="alt"><span>} </span></li> <li><span> </span></li> <li class="alt"><span><span class="value">#header</span><span> a </span></span></li> <li><span>{ </span></li> <li class="alt"><span> text-decoration : <span class="value">none</span><span>; </span></span></li> <li><span> border : <span class="value">none</span><span>; </span></span></li> <li class="alt"><span>} </span></li> <li><span> </span></li> <li class="alt"><span><span class="value">#header</span><span> </span></span></li> <li><span>{ </span></li> <li class="alt"><span> background : <span class="value">#fff</span><span> </span><span class="value">url</span><span>(</span><span class="string">"images/lb-h.jpg"</span><span>) </span><span class="value">repeat-x</span><span> </span><span class="value">top</span><span>; </span></span></li> <li><span> height : <span class="value">115px</span><span>; </span></span></li> <li class="alt"><span>} </span></li> <li><span> </span></li> <li class="alt"><span><span class="value">#header</span><span> img.logo </span></span></li> <li><span>{ </span></li> <li class="alt"><span> position : <span class="value">absolute</span><span>; </span></span></li> <li><span> border : <span class="value">none</span><span>; </span></span></li> <li class="alt"><span> margin-<span class="value">top</span><span> : </span><span class="value">10px</span><span>; </span></span></li> <li><span> margin-<span class="value">left</span><span> : </span><span class="value">50px</span><span>; </span></span></li> <li class="alt"><span> z-index : <span class="value">1000</span><span>; </span></span></li> <li><span>} </span></li> <li class="alt"><span> </span></li> <li><span><span class="comment">/* Top banner... */</span><span> </span></span></li> <li class="alt"><span><span class="value">#banner</span><span> </span></span></li> <li><span>{ </span></li> <li class="alt"><span> margin : <span class="value">0</span><span>; </span></span></li> <li><span> padding : <span class="value">0</span><span>; </span></span></li> <li class="alt"><span> background-color : <span class="value">#fff</span><span>; </span></span></li> <li><span> border-<span class="value">bottom</span><span> : </span><span class="value">1px</span><span> </span><span class="value">solid</span><span> </span><span class="value">#bebebe</span><span>; </span></span></li> <li class="alt"><span> height : <span class="value">265px</span><span>; </span></span></li> <li><span> text-align : <span class="value">center</span><span>; </span></span></li> <li class="alt"><span>} </span></li> <li><span> </span></li> <li class="alt"><span><span class="comment">/* This is the main content */</span><span> </span></span></li> <li><span><span class="value">#conten</span><span>t </span></span></li> <li class="alt"><span>{ </span></li> <li><span> background : <span class="value">#fff</span><span> </span><span class="value">url</span><span>(</span><span class="string">"images/lb-g.jpg"</span><span>) </span><span class="value">repeat-x</span><span> </span><span class="value">top</span><span>; </span></span></li> <li class="alt"><span> min-height : <span class="value">450px</span><span>; </span></span></li> <li><span> display : inline-<span class="value">block</span><span>; </span></span></li> <li class="alt"><span> clear : <span class="value">both</span><span>; </span></span></li> <li><span>} </span></li> <li class="alt"><span> </span></li> <li><span><span class="value">#footer</span><span> </span></span></li> <li class="alt"><span>{ </span></li> <li><span> border-<span class="value">top</span><span> : </span><span class="value">3px</span><span> </span><span class="value">solid</span><span> </span><span class="value">#bebebe</span><span>; </span></span></li> <li class="alt"><span> clear : <span class="value">both</span><span>; </span></span></li> <li><span> min-height : <span class="value">100px</span><span>; </span></span></li> <li class="alt"><span> font-size : <span class="value">smaller</span><span>; </span></span></li> <li><span>} </span></li> <li class="alt"><span> </span></li> <li><span><span class="value">#follow</span><span>icons </span></span></li> <li class="alt"><span>{ </span></li> <li><span> margin-<span class="value">left</span><span> : </span><span class="value">50px</span><span>; </span></span></li> <li class="alt"><span>} </span></li> </ol>
要压缩一个 CSS 文件,运行以下命令:
<ol class="dp-xml"><li class="alt"><span><span>java -jar yuicompressor-2.4.2.jar -o sample.min.css sample.css </span></span></li></ol>
文件被压缩之后,输出看起来如 清单 3 所示。清单是为了便于阅读进行了格式化的,但是 YUI Compressor 输出没有换行:您看到的都是在一行。
清单 3. 压缩后的 CSS 文件
<ol class="dp-xml"> <li class="alt"><span><span>body{font-family:Tahoma,Geneva,sans-serif;background-color:#e2e2e2;margin:0;padding:0;} </span></span></li> <li><span>#header,#content,#footer{padding 0;margin 0;width:100%;min-width:600px;}#header a{ </span></li> <li class="alt"><span>text-decoration:none;border:none;}#header{background:#fff url("images/lb-h.jpg") repeat-x </span></li> <li><span>top;height:115px;}#header img.logo{position:absolute;border:none;margin-top:10px; </span></li> <li class="alt"><span>margin-left:50px;z-index:1000;}#banner{margin:0;padding:0;background-color:#fff; </span></li> <li><span>border-bottom:1px solid #bebebe;height:265px;text-align:center;}#content{background:#fff </span></li> <li class="alt"><span>url("images/lb-g.jpg") repeat-x top;min-height:450px;display:inline-block;clear:both;} </span></li> <li><span>#footer{border-top:3px solid #bebebe;clear:both;min-height:100px;font-size:smaller;} </span></li> <li class="alt"><span>#followicons{margin-left:50px;} </span></li> </ol>
除了简单地删除空白和注释之外,YUI Compressor 还对您的 CSS 执行大量其他优化来使文件更小。那么,为了使文件更小究竟对 CSS 代码做了什么呢?
删除空白。任何不必要的空白,像缩进、空行,以及元素和括号之间的空格都被删除了。如果,CSS 的空白对于正常运行是必需的,那么会被保留下来(见 清单 4)。
清单 4. 删除多余的空白
<ol class="dp-css"> <li class="alt"><span><span> </span><span class="comment">/* Before */</span><span> </span></span></li> <li><span><span class="value">#header</span><span> a </span></span></li> <li class="alt"><span>{ </span></li> <li><span> text-decoration : <span class="value">none</span><span>; </span></span></li> <li class="alt"><span> border : <span class="value">none</span><span>; </span></span></li> <li><span>} </span></li> <li class="alt"><span> </span></li> <li><span><span class="comment">/* After */</span><span> </span></span></li> <li class="alt"><span><span class="value">#header</span><span> a{</span><span class="keyword">text-decoration</span><span>:</span><span class="value">none</span><span>;</span><span class="keyword">border</span><span>:</span><span class="value">none</span><span>;} </span></span></li> </ol>
删除注释。如果在您的 CSS 文件中必须包含注释,比如,公司的版权通告,您可以在注释中输入一个感叹号(!),通知 YUI Compressor 保留它(见 清单 5)。
清单 5. 除必要注释外,全部删除
<ol class="dp-css"> <li class="alt"><span><span> </span><span class="comment">/* Before */</span><span> </span></span></li> <li><span><span class="comment">/* This is the main content */</span><span> </span></span></li> <li class="alt"><span><span class="value">#conten</span><span>t </span></span></li> <li><span>{ </span></li> <li class="alt"><span> background : <span class="value">#fff</span><span> </span><span class="value">url</span><span>(</span><span class="string">"images/lb-g.jpg"</span><span>) </span><span class="value">repeat-x</span><span> </span><span class="value">top</span><span>; </span></span></li> <li><span> min-height : <span class="value">450px</span><span>; </span></span></li> <li class="alt"><span> display : inline-<span class="value">block</span><span>; </span></span></li> <li><span> clear : <span class="value">both</span><span>; </span></span></li> <li class="alt"><span>} </span></li> <li><span> </span></li> <li class="alt"><span><span class="comment">/* After */</span><span> </span></span></li> <li><span><span class="value">#conten</span><span>t{</span><span class="keyword">background</span><span>:</span><span class="value">#fff</span><span> </span><span class="value">url</span><span>(</span><span class="string">"images/lb-g.jpg"</span><span>) </span><span class="value">repeat-x</span><span> </span><span class="value">top</span><span>;</span><span class="keyword">min-height</span><span>:</span><span class="value">450px</span><span>; </span></span></li> <li class="alt"><span><span class="keyword">display</span><span>:inline-</span><span class="value">block</span><span>;</span><span class="keyword">clear</span><span>:</span><span class="value">both</span><span>;} </span></span></li> </ol>