【CSS編】ページスピードインサイトで「レンダリングを妨げるリソースの除外」の問題を解決する方法
PageSpeed Insightsで「改善できる項目」として、レンダリングを妨げるリソースの除外という項目が表示された時の対処方法です。
今回は【CSS編】になります。
ページの初回ペイントをリソースが阻害しています。クリティカルな JS や CSS はインラインで配信し、それ以外の JS やスタイルはすべて遅らせることをご検討ください。詳細
もう少し解りやすくすると・・
という意味合いです。
まずは、概要から説明していきます。
レンダリングを妨げるリソースとは
主に下記の2つになります。
JS(JavaScript)
ジャバスクリプト(プログラミング言語)の略。
例)
- 複数画像のスライドショー機能
- ページ上部に滑らかに戻る機能
- マップ・カレンダー・コメントフォーム
など・・色々な部分で使われています。
CSS(Cascading Style Sheets)
カスケーディング・スタイル・シート(プログラミング言語)の略。
例)
- 文字の色・大きさ・太さ・フォントの指定
- 背景色・背景画像の指定
- 画像の装飾・大きさの指定
など、デザインを指定するのに使われています。
これらのファイルは、通常下記のような形式で組み込まれています。
例)
<!DOCTYPE html>
<html lang="ja">
/* ~~~~省略~~~~ */
<head>
<link rel="stylesheet" type="text/css" href="/css/common.css"/> /* 共通デザイン */
<link rel="stylesheet" type="text/css" href="/css/home.css"/> /* TOPページ用デザイン */
<script type="text/javascript" src="/js/jquery-3.3.1.min.js"></script> /* 必須スクリプト */
<script type="text/javascript" src="/js/scroll.js"></script> /* なめらかスクロール */
</head>
<body>
/* ~~~~省略~~~~ */
</body>
</html>
5・6行目が CSSファイルの読み込み。
7・8行目が JavaScriptファイルの読み込みです。
レンダリングのイメージ
上から順番にレンダリング(翻訳・描画)していきます。
実際は下記の通り、各リンク先をダウンロードしながら ①→②→③→④→⑤の順番に読まれていきます。
①で common.css へ読み込みリクエストが発生。ダウンロードし読み込み終えないと②に進めない。(待ち時間が発生)
同様に④までを全て読み込み終えないと、⑤に辿り着けない。
本題:レンダリングを妨げるリソースの除外方法
クリティカルなCSSの特定
クリティカルなCSSとは
オンライン上で手軽に抽出できるツールがあります。
Critical Path CSS Generator
https://jonassebastianohlsson.com/criticalpathcssgenerator/
★使い方
①URLを入力
②ブロックしているCSS(ここでは common.css)の中身を全て貼り付ける。
③「Creat Critical Path CSS 」ボタンを押す。
④生成されたCSSを全て選択→コピーしておく。
CSSのインライン化
先程コピーしたCSSコードをインライン化してみます。
<!DOCTYPE html>
<html lang="ja">
/* ~~~~省略~~~~ */
<head>
<style>/* ここに生成されたCSSコードを貼り付ける*/</style>
<link rel="stylesheet" type="text/css" href="/css/common.css"/> /* 共通デザイン */
<link rel="stylesheet" type="text/css" href="/css/home.css"/> /* TOPページ用デザイン */
<script type="text/javascript" src="/js/jquery-3.3.1.min.js"></script> /* 必須スクリプト */
<script type="text/javascript" src="/js/scroll.js"></script> /* なめらかスクロール */
</head>
<body>
/* ~~~~省略~~~~ */
</body>
</html>
5行目になります。
<style>@charset "UTF-8";html{background:#EFEFEF}body{text-align:center}header{height:60px;background-color:#FFF}header .header-inner{width:1260px;margin:0 auto}header .logo{margin-top:15px}footer{background-color:#EFEFEF;padding:60px 0}#Page{text-align:left;margin:0 auto;background:#FFFFFF;min-width:1260px}#Wrap{width:1260px;margin:0 auto}.contents-body{float:left;width:860px;margin:40px 0;padding:0 20px}#MainImage{margin:0 auto;display:none}#Copyright{font-size:12px;color:#999;width:1260px;margin:0 auto}#SideBox h2{font-weight:bold}nav{background-color:#EFEFEF}nav ul.nav-menu{width:1260px;margin:0 auto}nav .nav-menu li a{display:block;font-size:14px;padding:15px 40px;text-decoration:none;color:#000;font-weight:bold}#SideBox{float:right;width:240px;padding:60px}#NewsList{width:540px;float:left;margin-right:60px}#NewsList li{border-bottom:1px solid #CCC;margin-bottom:20px;list-style:none}#BaserFeed{width:260px;float:left}.img-eye-catch{float:left;margin-right:20px;margin-bottom:20px}.img-eye-catch{float:left;margin-right:20px;margin-bottom:20px}.widget{margin-bottom:60px}.widget-area h2{font-weight:bold;font-size:20px}.clearfix:after{content:" ";display:block;clear:both;height:0}.clearfix{display:inline-block}.clearfix{display:block}nav .nav-menu{display:block;position:relative;list-style:none;margin:0;padding:0;z-index:15}nav .nav-item{list-style:none;display:inline-block;padding:0;margin:0}nav .nav-item>a{position:relative;display:inline-block;padding:0.5em 1em;margin:0 0 -1px 0;border:1px solid transparent}nav .sub-nav{position:absolute;display:none;padding:20px;border:1px solid #dedede;background-color:#fff;z-index:1}#MainImage{z-index:0}nav .sub-nav ul{display:inline-block;vertical-align:top;margin:0 1em 0 0;padding:0}nav .sub-nav li{display:block;list-style-type:none;margin:0;padding:0}nav .ul-level-2 a{padding:10px 20px!important}.ul-level-2{margin-left:40px}#SearchIndexQ{width:95%}</style>
この様なコードで囲む事でインライン化できます。
上記のサンプルソースでは、home.css もレンダリングをブロックしているので、common.css と同様にします。
<!DOCTYPE html>
<html lang="ja">
/* ~~~~省略~~~~ */
<head>
<style>@charset "UTF-8";html{background:#EFEFEF}body{text-align:center}header{height:60px;background-color:#FFF}header .header-inner{width:1260px;margin:0 auto}header .logo{margin-top:15px}footer{background-color:#EFEFEF;padding:60px 0}#Page{text-align:left;margin:0 auto;background:#FFFFFF;min-width:1260px}#Wrap{width:1260px;margin:0 auto}.contents-body{float:left;width:860px;margin:40px 0;padding:0 20px}#MainImage{margin:0 auto;display:none}#Copyright{font-size:12px;color:#999;width:1260px;margin:0 auto}#SideBox h2{font-weight:bold}nav{background-color:#EFEFEF}nav ul.nav-menu{width:1260px;margin:0 auto}nav .nav-menu li a{display:block;font-size:14px;padding:15px 40px;text-decoration:none;color:#000;font-weight:bold}#SideBox{float:right;width:240px;padding:60px}#NewsList{width:540px;float:left;margin-right:60px}#NewsList li{border-bottom:1px solid #CCC;margin-bottom:20px;list-style:none}#BaserFeed{width:260px;float:left}.img-eye-catch{float:left;margin-right:20px;margin-bottom:20px}.img-eye-catch{float:left;margin-right:20px;margin-bottom:20px}.widget{margin-bottom:60px}.widget-area h2{font-weight:bold;font-size:20px}.clearfix:after{content:" ";display:block;clear:both;height:0}.clearfix{display:inline-block}.clearfix{display:block}nav .nav-menu{display:block;position:relative;list-style:none;margin:0;padding:0;z-index:15}nav .nav-item{list-style:none;display:inline-block;padding:0;margin:0}nav .nav-item>a{position:relative;display:inline-block;padding:0.5em 1em;margin:0 0 -1px 0;border:1px solid transparent}nav .sub-nav{position:absolute;display:none;padding:20px;border:1px solid #dedede;background-color:#fff;z-index:1}#MainImage{z-index:0}nav .sub-nav ul{display:inline-block;vertical-align:top;margin:0 1em 0 0;padding:0}nav .sub-nav li{display:block;list-style-type:none;margin:0;padding:0}nav .ul-level-2 a{padding:10px 20px!important}.ul-level-2{margin-left:40px}#SearchIndexQ{width:95%}</style>
<link rel="stylesheet" type="text/css" href="/css/common.css"/>
<style>/* ここに生成されたCSSコードを貼り付ける(home.css)*/</style>
<link rel="stylesheet" type="text/css" href="/css/home.css"/>
<script type="text/javascript" src="/js/jquery-3.3.1.min.js"></script> /* 必須スクリプト */
<script type="text/javascript" src="/js/scroll.js"></script> /* なめらかスクロール */
</head>
<body>
/* ~~~~省略~~~~ */
</body>
</html>
link rel=”preload” を追記する
次に、linkタグのrel属性の値を rel="preload" に変更し、as="style" を追記します。
<style>生成されたコード</style>
<link rel="preload" type="text/css" href="/css/common.css" as="style">
preload は、href 属性で指定したURLのコンテンツを先読みするための指定です。
これにより、レンダリングブロックを回避しながらCSSを読み込むことができます。
<link rel="preload"> ブラウザ対応状況
Can I use でチェックした所、本記事作成時点では、IE および Firefox などに対応していません。
なので、rel=”preload” 未対応ブラウザにも、preload と同じ役割を持たす追記をしていきます。
loadCSS の導入
loadCSS という JavaScript を利用させて頂きます。
https://github.com/filamentgroup/loadCSS
こちらを利用するには、下記の JavaScript コード が必要になりますのでコピーしておきます。
https://github.com/filamentgroup/loadCSS/blob/master/src/cssrelpreload.js
実装方法
<head>
<style>インラインCSSコード</style>
<link rel="preload" href="/css/common.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/common.css"></noscript>
<script>
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
/* This file is meant as a standalone workflow for
– testing support for link[rel=preload]
– enabling async CSS loading in browsers that do not support rel=preload
– applying rel preload css once loaded, whether supported or not.
*/
(function( w ){
"use strict";
// rel=preload support test
if( !w.loadCSS ){
w.loadCSS = function(){};
}
//以下全てを貼り付ける
</script>
</head>
解説
3行目:onload="this.onload=null;this.rel=’stylesheet'" の追記。
4行目:スクリプトが使えない環境時に読み込ませる代替CSS
6行目:MITライセンス表記。絶対に消してはいけません。
7~11行目:コードの説明。消してもOK
12行目:※メインスクリプト(縮小するのがおすすめ)
※スクリプトも CSS と同様に <script>コード</script> でインライン化できます。
以下、本記事で紹介しているサンプルコードになります。
レンダリングをブロックするCSSのインライン化と妨げにならないCSSの記述例
<!DOCTYPE html>
<html lang="ja">
/* ~~~~省略~~~~ */
<head>
<style>インラインCSSコード(common)</style>
<style>インラインCSSコード(home)</style>
<link rel="preload" href="/css/common.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/common.css"></noscript>
<link rel="preload" href="/css/home.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/home.css"></noscript>
<script>
/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */
(function(a){if(!a.loadCSS){a.loadCSS=function(){}}var b=loadCSS.relpreload={};b.support=(function(){var d;try{d=a.document.createElement("link").relList.supports("preload")}catch(f){d=false}return function(){return d}})();b.bindMediaToggle=function(e){var f=e.media||"all";function d(){if(e.addEventListener){e.removeEventListener("load",d)}else{if(e.attachEvent){e.detachEvent("onload",d)}}e.setAttribute("onload",null);e.media=f}if(e.addEventListener){e.addEventListener("load",d)}else{if(e.attachEvent){e.attachEvent("onload",d)}}setTimeout(function(){e.rel="stylesheet";e.media="only x"});setTimeout(d,3000)};b.poly=function(){if(b.support()){return}var d=a.document.getElementsByTagName("link");for(var e=0;e<d.length;e++){var f=d[e];if(f.rel==="preload"&&f.getAttribute("as")==="style"&&!f.getAttribute("data-loadcss")){f.setAttribute("data-loadcss",true);b.bindMediaToggle(f)}}};if(!b.support()){b.poly();var c=a.setInterval(b.poly,500);if(a.addEventListener){a.addEventListener("load",function(){b.poly();a.clearInterval(c)})}else{if(a.attachEvent){a.attachEvent("onload",function(){b.poly();a.clearInterval(c)})}}}if(typeof exports!=="undefined"){exports.loadCSS=loadCSS}else{a.loadCSS=loadCSS}}(typeof global!=="undefined"?global:this));
</script>
</head>
<body>
/* ~~~~省略~~~~ */
</body>
</html>
5・6行目で、インラインCSSをまとめています。実際はかなり長くなります。
<style>common+home</style>と合体させずに、
<style>common</style><style>home</style> と分けてあげる方がメンテナンス性が良いです。
★トップページ以外は使用しないCSSなので。
11行目からの <script>~</script> の記述は1つでOKです。(各ページ毎に)
PageSpeed Insightsで再チェック
指摘されていた CSS の表示が消えました。
また、Firefox や IE でサイトが正しく表示されるかもチェックしましょう。
インライン化する上での注意点
- インライン化することで、CSSで指定している画像やウェブフォントなどのパスが変わり、表示されないことがあります。
- CSSの圧縮方法でも触れましたが、縮小時にコードが崩れる事があります。
これらを直せる位の知識が必要になります。
また、ウェブサイトの種類によっては、全ページを手動で記述していく必要があったり・・デザイン変更時のメンテナンス性が悪くなります。
エレメント化 や テンプレ化 するなどして、メンテナンス性を落とさない工夫も必要かと思います。
最後に・・
レンダリングを妨げるリソースの除外という項目は、一番上に表示されるだけあってかなり重要な項目になっています。
改善できると、多くの方が体感できる位に表示速度が変わります。
次回は、レンダリングを妨げるリソースのJavaScript編をお届けします。
参考になれば幸いです。
ディスカッション
コメント一覧
とてもわかりやすい記事で助かりました!レンダリングの順番とかも図解されており初心者でもわかりやすかったです。
相当親切な記事だと思うんですが、これで難しい方は読解力なり検索力をつけた方がいいのではないでしょうか。
Critical Path CSS Generator のツールから、オンライン上で手軽に抽出方法など、素人でも理解し設定できる方法を詳細に明記して頂きたい。
「レンダリングを妨げるリソースの除外」を改善するためにいろいろと調べていました。
記事ありがとうございました。ですが・・・読んでも私には難しすぎて、、、
ごめんなさい。でも全くといってよいほど記事の内容が専門的過ぎて理解できません。。
初心者向けのご説明は可能でしょうか?
もしくは、初心者でも実践できるサイトがご存じなら教えていただけると嬉しいです。。