[対象: 中〜上級]

僕のブログではてブ数がいちばん多いのはウェブページを高速化するTIPSを解説した記事です(まだ読んでない人はぜひ読んでください!)。

その記事では高速化全般を扱っていましたが、今日の記事ではJavaScriptに的を絞って表示速度をスピードアップできる施策を6つ紹介します。

もともとはSearch Engine PeopleブログOptimizing JavaScript for Better Web Performanceで説明されていたものです。

記事作者のJoydeep Deb(ジョイディープ・デブ)氏に僕のブログでの転載許可をもらえました (Thanks, Joydeep!)。

逐一の翻訳ではなく、書かれている内容をもとに僕の言葉で解説していきます。

1. HTTPリクエスト削減のためにJavaScriptファイルを1つに統合する

ウェブページの表示を高速化する秘訣の1つは、HTTPリクエストの数を減らすことです(1枚のウェブページであっても、HTMLファイル本体や画像、スクリプトなどをダウンロードするためにウェブサーバーとブラウザはバックグラウンドで何回も何回もやり取りしている)。

HTTPリクエストの数を減らすために複数のファイルに分かれているJavaScriptを1つのファイルにまとめます。

JavaScriptを複数ファイルに分けた悪い例:

<script src="http://www.example.com/menu.js"></script>
<script src="http://www.example.com/ajax.js"></script>
<script src="http://www.example.com/nav.js"></script>
<script src="http://www.example.com/tools.js"></script>
<script src="http://www.example.com/footer.js"></script>
<script src="http://www.example.com/others.js"></script>

JavaScriptを1ファイルにまとめた良い例:

<script src="http://www.example.com/combined-all.js"><</script>

上の例では、ファイルを1つに統合することにより6回発生していたHTTPリクエストを1回に減らせます。
アクセス数の多いサイトでは特に効果が期待できます。

2. CSSの参照タグをJavaScriptの参照タグよりも先に記述する

HTMLのheadセクションでは、スタイルシートの参照を先に記述しその後にJavaScriptの参照を記述します。

JavaScriptタグよりも後ろにCSSタグを記述する悪い例

<head>
  <script src="http://www.example.com/nav.js"></script>
  <script src="http://www.example.com/tools.js"></script>
  <script src="http://www.example.com/footer.js"></script>
  <link rel="stylesheet" type="text/css" href="stylesheet1.css" />
  <link rel="stylesheet" type="text/css" href="stylesheet2.css" />
</head>

JavaScriptタグの前にCSSタグを記述する良い例

<head>
  <link rel="stylesheet" type="text/css" href="stylesheet1.css" />
  <link rel="stylesheet" type="text/css" href="stylesheet2.css" />
  <script src="http://www.example.com/nav.js"></script>
  <script src="http://www.example.com/tools.js"></script>
  <script src="http://www.example.com/footer.js"></script>
</head>

JavaScriptは読み込みが始まるとその読み込みが完了して実行されるまでは次のコードの読み込みが始まりません。
待ち時間が発生するわけですね。

一方でスタイルシートの読み込みは複数が同時に行えるし完了していなくてもJavaScriptファイルを含む他のファイル読み込むことができます。

元記事には書いていないことの補足として、特に良くないのは複数のスタイルシート参照の間にJavaScript参照を挟んでしまうことで速度を大きく低下させる可能性があります。

CSS参照タグの間にJavaScript参照タグを挟むとても悪い例

<head>
  <script src="http://www.example.com/nav.js"></script>
  <link rel="stylesheet" type="text/css" href="stylesheet1.css" />
  <script src="http://www.example.com/tools.js"></script>
  <link rel="stylesheet" type="text/css" href="stylesheet2.css" />
  <script src="http://www.example.com/footer.js"></script>
</head>

3. プロトコルを省略する

JavaScriptの外部ファイルを示すURLから http: または https: といったプロトコル(スキーム)を省略します。
省略することでファイルサイズを(ごくわずかだけれど)小さくできます。

プロトコルを省略しない悪い例:

<script src="http://www.example.com/scripts/javascript.js"></script>

プロトコルを省略した良い例:

<script src="//www.example.com/scripts/javascript.js"></script>

プロトコルが省略されている時はそのページの表示に使われている(ブラウザのアドレスバーに表示される)プロトコルが自動的に適用されます。

つまり https: で表示しているなら参照先にも自動的に https: が使われます。

ちなみにJavaScriptだけでなくCSSでも画像でも何でもプロトコルはURLから省略可能です。
ただし省略した場合は、http: なら http: で、https: なら https: でその外部リソースを参照できなければなりません。

4. script要素のtype属性を省略する

HTML5に限りますが、script要素におけるtype属性すなわち type="text/javascript" を省略します。
HTML5では、script要素のtype属性の初期値が "text/javascript" になっているからです。

省略することで(ごくわずかに)ファイルサイズを小さくできます。

type属性を省略していない悪い例:

<script src="//www.example.com/scripts/javascript.js" type="text/javascript"></script>

type属性を省略した良い例:

<script src="//www.example.com/scripts/javascript.js"></script>

なおHTML5では、style要素のtype属性の初期値は "text/css" になっているので type="text/css" も同様に省略可能です。

5. Expiresヘッダーでキャッシュ期間を長くする

ブラウザは1度ダウンロードしたデータをローカルにキャッシュします。
再度同じデータが必要になった時はローカルにキャッシュがあればサーバーにリクエストせずにキャッシュデータを利用します。
すでに自分が持っているデータを使うのでレスポンスが速くなります。

キャッシュは期限が切れると削除されますが、ExpiresというHTTPヘッダーを使うとキャッシュ期間の強制的な指定が可能です。

ウェブサーバーがApacheの場合、.htaccessまたはhttpd.confでExpiresヘッダーを設定するとJavaScriptのキャッシュ期間を制御できます。

たとえば下のように記述できます。

<IfModule mod_headers.c>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/javascript "access plus 4 weeks"
ExpiresByType application/x-javascript "access plus 4 weeks"
ExpiresByType application/javascript "access plus 4 weeks"
</IfModule>
</IfModule>

JavaScriptファイルに最初にアクセスした時から4週間が過ぎるとキャッシュが期限切れして消えます。
言い換えると4週間はローカルにキャッシュが残ります。

期間の指定方法には種類があります。
詳細はApacheのドキュメントを参照してください。

なおサーバーにmod_expiresモジュールがインストールされていないと機能しません。

またJavaScriptだけでなく他のコンテンツのキャッシュ期間の制御にもExpiresヘッダーは使えます。

僕は画像ファイルのキャッシュ期間も設定しています。

ExpiresByType image/gif "access plus 4 weeks"
ExpiresByType image/jpeg "access plus 4 weeks"
ExpiresByType image/png "access plus 4 weeks"

ファイルタイプ(MIMEタイプ)の指定もApacheのドキュメントを読んでください。

JavaScriptのファイルタイプはドキュメントには書かれていなくて調べたところいくつかあるようです。
サーバーの環境や利用しているCMSによって違っていて一般的に使われている3つの種類を僕は記述しています。

具体的な記述は元記事に書かれていません。
僕が自分で調べて以前から利用していた記述を紹介しました(もっと適切な記述を知っていたら教えてください)。

キャッシュ期間をどのくらいに設定するかが問題ですが、これは自分で考えてもらうしかありません。
僕が設定している「4週間」に合理的な意味があるわけではありません。
「これくらいでいいかな」で決めました。(笑)
※RFCに従えば1年以上の期間を指定してはいけないようです。

またhttpd.confではなくて.htaccessに書くのなら「4 weeks」よりも数値のほうがパフォーマンスがよくなるかもしれません。

注意しなければならないことは、まったくあるいはほとんど更新がない静的なファイルにExpiresヘッダーを使うことです。
更新してもキャッシュを使ってしまうのでブラウザに残っている古いデータが使われてしまうからです。

更新した場合はファイルの名前を変えるといいでしょう(初めてリクエストするファイルにしてしまう)。

キャッシュの制御としてはプロキシキャッシュを活用することもできます。

元記事には簡単にしか触れられていないので僕自身で調べた解説になります。

たとえば通信経路途中のISPでプロキシサーバーが使われているときは、そのプロキシサーバーにもファイルがキャッシュされます。

たとえあなたが初めてアクセスするサイトであっても同じプロキシサーバーを利用している他のユーザーがアクセスしたことのあるページであればプロキシサーバーにあるキャッシュデータが返されます。

ウェブサーバーまでの通信が発生しないので応答スピードが結果として速くなります。

プロキシキャッシュをコントロールするにはCache-Controlヘッダーを設定します。

たとえばこんなふうに記述できます。

<IfModule mod_headers.c>
<FilesMatch "\.(jpg|png|gif|swf|ico|css|js)$">
Header set Cache-Control "max-age=2419200, public"
</FilesMatch>
</IfModule>

JavaScript以外にも、画像やCSSなどのその他の静的ファイルも含めています。
キャッシュの保持期間は4週間にセットしてあります。

注意点があります。

CSSとJavaScriptをCache-Controlヘッダーでキャッシュさせるときは、ある製品のプロキシサーバーではバグによりうまく機能しないことがあるようです。

Vary: Accept-Encoding ヘッダーを併用することで回避できます(たいていのサーバーでは実装されているはず。詳細は最後に載せるドキュメントで確認してください。)。

6. コメントを削除する

JavaScriptファイルに書き込まれている不要なコメントを削除します。

フィアルサイズが小さくなりブラウザの読み込みが速くなります。

HTMLファイルやCSSファイルにもコメント削除の効用は当てはまります。

もっとも体感的にどのくらいスピードアップするかどうかは疑問ですけどね。
「やれるならやっておけば」程度でしょうか。

以上がウェブサイトでのJavaScriptの読み込みを最適化してウェブページの表示速度を改善する6つの方法です。

キャッシュのところがひょっとすると難しかったかもしれませんね。

もっとも動きを知らなくても.htaccessに追加すれば普通は機能するので何も考えずに実装することができるでしょう(とは言え自己責任でお願いします)。

JavaScriptファイルの統合と参照タグの配置についてはあなたのサイトではどうなってるかさっそく見直してみてください。

余分な記述を省くファイルサイズの削減による読み込み速度の改善は目に見えるほどの大きな効果はなような気がしますが気休め程度にやってみるのも悪くはないはずです。

今回、利用を許可してくれたJoydeep氏の記事を日本語解説する際は、理解度を確かにしてうまく説明できるように自分でもいろいろ調べました。

調べる過程で発見したのですが、Joydeep氏は以下のドキュメントからも多数の情報を引っ張ってきています。
すべて英語になりますが、より詳しいことに加えてJavaScript以外のスピードアップ方法もたくさん説明されているので読んでおくと絶対に得します。

このエントリーが役に立ったらシェアしてください

[Ads & Featured Articles]

次のエントリも読むとSEOにさらに強くなります。

海外SEO情報ブログTOPUX・IA・CRO・EFO › JavaScriptの読み込みを最適化してページの表示速度を高速化する6つの方法

Comments

  1. By Shin on

    鈴木様
    いつもお世話になります。

    有効期限がずっと先のExpiresヘッダーを返す。
    Expires: Tue, 06 June 2023 20:00:00 GMT
    https://www.suzukikenichi.com/blog/website-performance-optimization/
    と、
    .htaccessまたはhttpd.confでExpiresヘッダーを設定する

    ExpiresActive On
    ExpiresByType text/javascript “access plus 4 weeks”
    ExpiresByType application/x-javascript “access plus 4 weeks”
    ExpiresByType application/javascript “access plus 4 weeks”

    は、何がどう違うのでしょうか?

    *** Reply from Suzuki Kenichi ***
    前者は具体的にキャッシュが切れる日時を指定しています。
    ずっと先の未来にすることで、実質的にキャッシュ切れにならないようにするわけですね。

    一方後者は、アクセスした時点からのキャッシュ切れまでの期間を指定しています。
    ここでは「4週間後に切れる」ようにしています。
    “access plus 3 years” にすれば3年後に切れます。

    mod_expiresの詳細はApacheのドキュメントをご参照ください。
    http://httpd.apache.org/docs/2.4/mod/mod_expires.html

  2. By Shin on

    すみません。
    読んでみたのですが、理解の仕方が。。。
    私の理解として、前者の方は.htaccessが使えない環境の時にhtml内に書き、
    .htaccessが使えるのであれば後者を使うイメージなのですが、
    この理解の仕方はあっていますか?

    *** Reply from Suzuki Kenichi ***
    違います。
    どちらもhtaccessまたはhttpd.confに記述します。

    根本的なところで十分に理解できていないようです。
    「ExpiresByType」で検索すると詳しく説明しているサイトがたくさんあるのでご自身で調べてみてください。

  3. By Shin on

    何度もすみません。
    やはり、Expires: Tue, 06 June 2023 20:00:00 GMTといった書き方をするのは、
    (””内は有効期限)や、
    phpで書くようなheader(“Expires: Tue, 30 Sep 2023 23:00:00 GMT”)(””内は有効期限)ではないのでしょうか?

    単に書き方だけの疑問でしたので、これほどこだわることでもないのかもしれませんが。。。
    申し訳ありません。

    *** Reply from Suzuki Kenichi ***
    失礼しました。

    おっしゃるように、Expires: Tue, 06 June 2023 20:00:00 GMT はここではApacheの設定とは関係なく、HTTPヘッダーで返される内容を示したものです。
    ExpiresByTypeで指定する時間は、「A86400」のようにAまたはMに続けて秒数を付けるか、access plus 1 yearのようにするかですね。

    再度調べたことで僕も勉强になりました。
    ご質問ありがとうございました。

▲ページの一番上に戻る