Webページのレンダリング遅延を改善し、高速化
PageSpeed Insightsのパフォーマンス測定をすると、スクロールせずに見えるコンテンツ(ファーストビュー)のレンダリングをブロックしているJavaScript/CSSを排除するよう促された。
レンダリングを妨げられるとその分だけ表示が遅くなるので、できれば改善すべきである。
小さいサイズのJavaScriptやCSSなら、PageSpeed Insightsで提案していたようにコードをHTMLドキュメントに直接挿入してインライン化すればいいが、大きいサイズだと最初のレンダリングで読み込む量が増えるので逆に遅くなる。
WordPressだと高速化のプラグインを使えばある程度は改善するが、すべてではないのでいくつかの方法を試みる。
CSSの読み込みを遅延または非同期にする
requestAnimationFrameを使用して遅延する
<script>
requestAnimationFrame(function(e) {
e = document.createElement(‘link’);
e.rel = ‘stylesheet’;
e.href = ‘<?php echo get_stylesheet_uri(); ?>’;
document.head.appendChild(e);
});
</script>
描画が終わったタイミングでheadタグ内にタグを生成する。ただし、IE9以下では動かない。
loadCSSを使用して非同期にする
headタグ内に以下を記述。
<link rel=”preload” href=”<?php echo get_stylesheet_uri(); ?>” as=”style” onload=”this.onload=null;this.rel=’stylesheet'”>
<noscript><link rel=”stylesheet” href=”<?php echo get_stylesheet_uri(); ?>”></noscript>
<script>
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
!function(t){“use strict”;t.loadCSS||(t.loadCSS=function(){});var e=loadCSS.relpreload={};if(e.support=function(){var e;try{e=t.document.createElement(“link”).relList.supports(“preload”)}catch(a){e=!1}return function(){return e}}(),e.bindMediaToggle=function(t){function e(){t.media=a}var a=t.media||”all”;t.addEventListener?t.addEventListener(“load”,e):t.attachEvent&&t.attachEvent(“onload”,e),setTimeout(function(){t.rel=”stylesheet”,t.media=”only x”}),setTimeout(e,3e3)},e.poly=function(){if(!e.support())for(var a=t.document.getElementsByTagName(“link”),n=0;n<a.length;n++){var o=a[n];”preload”!==o.rel||”style”!==o.getAttribute(“as”)||o.getAttribute(“data-loadcss”)||(o.setAttribute(“data-loadcss”,!0),e.bindMediaToggle(o))}},!e.support()){e.poly();var a=t.setInterval(e.poly,500);t.addEventListener?t.addEventListener(“load”,function(){e.poly(),t.clearInterval(a)}):t.attachEvent&&t.attachEvent(“onload”,function(){e.poly(),t.clearInterval(a)})}”undefined”!=typeof exports?exports.loadCSS=loadCSS:t.loadCSS=loadCSS}(“undefined”!=typeof global?global:this);
</script>
JavaScriptの読み込みを遅延または非同期にする
JavaScriptの読み込みを遅延または非同期にすることでJavaScriptによるレンダリングの妨げを回避し、高速化できる。
async属性を使用して非同期にする
HTMLに記述の場合
<script async src=”abc.js”>
PHP(WordPress使用時はfunctions.php)に記述の場合
function replace_script_tag ( $tag ) {
return str_replace( “type=’text/javascript'”, ‘async’, $tag );
}
add_filter( ‘script_loader_tag’, ‘replace_script_tag’ );
上記の場合ではすべてのjavascriptが対象になります。
単一abc.jsだけに反映させたい場合は
function replace_script_tag ( $tag ) {
if(preg_match(‘/abc¥.js/’,$tag)){
return str_replace( “type=’text/javascript'”, ‘async’, $tag );
}
}
add_filter( ‘script_loader_tag’, ‘replace_script_tag’ );
async属性を使用するとdocument.writeやJavaScriptライブラリのjQueryなどが読み込めなかったり、不具合がでるので、その場合は遅延させるdeferを使います。
アドネットワークサービスのnendはasync、defer共に使用すると読み込めなくなります。
HTML5ではインラインスクリプトには使用できません。
defer属性を使用して遅延させる
HTMLに記述の場合
<script defer src=”abc.js”>
PHP(WordPress使用時はfunctions.php)に記述の場合
function replace_script_tag ( $tag ) {
return str_replace( “type=’text/javascript'”, ‘defer’, $tag );
}
add_filter( ‘script_loader_tag’, ‘replace_script_tag’ );
上記の場合もasync属性での設定と同様すべてのjavascriptが対象になります。個別に設定したい場合は
function replace_script_tag ( $tag ) {
if(preg_match(‘/abc¥.js/’,$tag)){
return str_replace( “type=’text/javascript'”, ‘defer’, $tag );
}
}
add_filter( ‘script_loader_tag’, ‘replace_script_tag’ );
HTML5ではインラインスクリプトには使用できません。
JavaScriptをフッターに移動させる
JavaScriptはヘッダーに設置することが多くあり、ファーストビューでコンテンツより先に読み込もうとするのでその分表示が遅くなる。
なのでファーストビュー範囲外のフッターに設置することでコンテンツ表示を優先させて高速化する。
WordPress
functions.phpに記述。
if(!is_admin()){
remove_action(‘wp_head’, ‘wp_print_head_scripts’, 9);
add_action(‘wp_footer’, ‘wp_print_head_scripts’, 5);
}
wp_head()で読み込まれるjQueryおよび他のJavaScriptをフッターに移動します。
[ad#ads]
CDN(コンテンツ・デリバリー・ネットワーク)を利用する
jQueryなどのCDNサービスがあるJavaScriptを外部のサーバーから読み込むことで負荷が分散され、キャッシュ効果も効いて高速化できる。
CDNサービスが廃止されたり、CDNのサーバーがダウンして読み込めなくなるのが心配なら自前のjQueryと併用すれば問題ない。
WordPress
functions.phpに記述。
function reregistration_jquery(){
if(!is_admin()){
wp_deregister_script(‘jquery’);
wp_enqueue_script(‘jquery’,’//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js’,array(),null,true );
}
}
add_action(‘wp_enqueue_scripts’, ‘reregistration_jquery’);
上記はフッターに移動させる記述だが、AddToAny Share Buttonsなどのプラグインを使用しているとフッターには移動しない。
そこで、下記のようにwp_head()で読み込まれるJavaScriptをすべてフッターに移動させればできる。
remove_action(‘wp_head’, ‘wp_print_head_scripts’, 9);
add_action(‘wp_footer’, ‘wp_print_head_scripts’, 5);
function reregistration_jquery(){
if(!is_admin()){
wp_deregister_script(‘jquery’);
wp_enqueue_script(‘jquery’,’//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js’,array(),null,true );
}
}
add_action(‘wp_enqueue_scripts’, ‘reregistration_jquery’);
ブラウザのキャッシュを活用する
ブラウザのキャッシュを使用することでサーバーからの読み込む量が減少されるので、表示が高速化されます。
.htaccessを設置してブラウザキャッシュを設定
.htaccessでキャッシュを設定するにあたって、サーバー側でモジュールmod_expiresに対応している必要があります。
.htaccessは、設置したディレクトリ以下に適用されます。
以下を記述。
# キャッシュ設定
<IfModule mod_headers.c>
<ifModule mod_expires.c>
ExpiresActive On
# キャッシュ初期化(1秒に設定)
ExpiresDefault “access plus 1 seconds”
# MIME Type ごとの設定
ExpiresByType text/css “access plus 1 weeks”
ExpiresByType text/js “access plus 1 weeks”
ExpiresByType text/javascript “access plus 1 weeks”
ExpiresByType image/gif “access plus 1 weeks”
ExpiresByType image/jpeg “access plus 1 weeks”
ExpiresByType image/png “access plus 1 weeks”
ExpiresByType image/svg+xml “access plus 1 year”
ExpiresByType application/pdf “access plus 1 weeks”
ExpiresByType application/javascript “access plus 1 weeks”
ExpiresByType application/x-javascript “access plus 1 weeks”
ExpiresByType application/x-shockwave-flash “access plus 1 weeks”
ExpiresByType application/x-font-ttf “access plus 1 year”
ExpiresByType application/x-font-woff “access plus 1 year”
ExpiresByType application/x-font-woff2 “access plus 1 year”
ExpiresByType application/x-font-opentype “access plus 1 year”
ExpiresByType application/vnd.ms-fontobject “access plus 1 year”
</ifModule>
</ifModule>
めも
ブラウザのキャッシュを無視し、強制的にWebサーバーからファイルを読み込む(スーパーリロード)にはctrl + f5
[ad#ads-txt]
プラグインを使用する
WordPressならプラグインのWP Fastest Cacheなどを導入することでキャッシュだけでなく、js、cssの結合や圧縮などでも高速化をすることができます。
うまく使えばページの読み込みを十分高速化してくれるが、他のプラグインなどのファイルに干渉するので注意して使用しないとサイト自体や他のプラグインが読み込めなくなったりすることもある。
ファイルを圧縮して通信量を減らす
読み込むファイルを圧縮してサイズを小さくすれば通信量が減り、それだけ速くなります。
サーバー側でgzip圧縮
サーバー側でzip圧縮をするには、サーバー側がモジュールmod_deflateに対応している必要があります。
.htaccessに以下を記述。(設置したディレクトリ以下に適用されます。)
# gzip圧縮設定
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
# Mozilla4系、IE7、8の古いブラウザでは無効にする
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch \bMSIE\s(7|8) !no-gzip !gzip-only-text/html
# 圧縮済みのコンテンツは再圧縮しない
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico|eot|woff|woff2)$ no-gzip dont-vary
#ファイルを圧縮
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/js
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-font-ttf
#AddOutputFilterByType DEFLATE application/x-font-woff
#AddOutputFilterByType DEFLATE application/x-font-woff2
AddOutputFilterByType DEFLATE application/x-font-opentype
#AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
</IfModule>
自前でgzip圧縮
サーバー側でgzip圧縮できない場合は7-zipなどでファイルをgzip圧縮してアップロード。
圧縮前のファイルは削除せずにそのまま同じ場所に置いておく。
.htaccessに以下を記述。
#gzip圧縮受け渡し
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:Accept-Encoding} gzip
RewriteCond %{REQUEST_FILENAME} “\.(css|js|html?|xml|php)$”
RewriteCond %{REQUEST_FILENAME} !”\.gz$”
RewriteCond %{REQUEST_FILENAME}.gz -s
RewriteRule .+ %{REQUEST_URI}.gz [L]
AddEncoding x-gzip .gz
</IfModule>
これであとはブラウザ側で展開処理してくれますが、ファイルタイプの関連付けをしないと圧縮はできても、うまく読み込めなくなるのでAddEncoding x-gzip .gzの部分を以下のように書き換えたほうがいいかも。(当方で試したサーバーではAddTypeやAddHandlerなどが対応してなくて試してない)
AddType application/x-httpd-php .php
<files *.css.gz>
AddType “text/css” .gz
AddEncoding gzip .gz
</files>
<files *.js.gz>
AddType “text/javascript” .gz
AddEncoding gzip .gz
</files>
<files *.html.gz>
AddType “text/html; charset=utf-8” .gz
AddEncoding gzip .gz
</files>
<files *.xml.gz>
AddType “text/xml” .gz
AddEncoding gzip .gz
</files>
<files *.php.gz>
AddType “AddType application/x-httpd-php .php” .gz
AddEncoding gzip .gz
</files>
まとめ
CDNのjQuery(JavaScript)を使用し、JavaScriptはフッターに移動させて非同期か遅延させ、キャッシュ使用やファイル圧縮をするのが高速化の第一歩。