以前から試してみたかった、JSやCSSなどの外部ファイルをインラインでフッターに出力する仕組みを試作しました。
なお、バッドノウハウといいいますか、そもそもこの処理を行う必要性に疑問があるといいますか、他の方にお勧めできる内容ではないと思います。
実現したいこと
実現したいことは以下の通り。
- WordPressのテーマ内のJSとCSSをインラインで出力
- 出力先はフッター
CSSに関してはフッターに書いてどうするという感じもしますが、JSに限らず試してみたかったのでCSSも込みで記載しています。
インラインにすると外部ファイルのようなキャッシュの恩恵がなくなりますが、小さなサイズのファイルであれば表示速度の向上に繋がる、かもしれません。
JSにしろCSSにしろ、当サイトで試したところ実感はありませんでしたが。
コード
//ファイルが存在するかチェックを行ってから取得する
function my_check_wp_remote_get( $file_url ){
$file = wp_remote_get( $file_url );
$check = wp_remote_retrieve_response_code( $file );
if( (int)$check === 200 ) {
$file = wp_remote_retrieve_body( $file );
} else {
$file = null;
}
return $file;
}
//CSS用
function my_inline_styles() {
if( is_singular() ) {
$url = get_stylesheet_directory_uri();
$out = my_check_wp_remote_get( $url . '/js/inline.css' );
}
if($out !== null){
//改行を削除
$out = str_replace(array("\r", "\n"), '', $out);
echo '<style type="text/css">' . $out . '</style>';
}
}
add_action( 'wp_footer', 'my_inline_styles' , 20 );
//JS用
function my_inline_scripts() {
$url = get_stylesheet_directory_uri();
$out = my_check_wp_remote_get( $url . '/js/inline.js' );
if( is_singular() ) {
$out1 = my_check_wp_remote_get( $url . '/js/inline-singular.js' );
$out .= $out1;
}
if( $out !== null ){
echo '<script type="text/javascript">' . $out . '</script>';
}
}
add_action( 'wp_footer' , 'my_inline_scripts' , 20 );
上がCSSで下がJSですが、どちらもwp_footerにフックしてフッターに出力しています。なお優先度は適当です。
JSのほうは2つのJSの中身を連結していますが、必須の処理では無い上にインライン化した時点であまり意味がない動作かなと思います。
cssはwp_add_inline_style()を使えばheadには出力できるのですが、現時点ではfooterに出力できないようなので、今回は使っていません。
一応wp_remote_retrieve_response_code()を使ってwp_remote_get()で取得したレスポンスが正常かどうかをステータスコードで判定しています。
詳細は以下で確認できます。
wp_remote_get
以前に「jQueryのCDNがアクセス可能かどうか調べて、アクセス不可ならローカルのjQueryを読み込む」というコードを作った際に、wp_remote_get()で別ドメインにアクセスできるかどうかの判定に使いました。
wp_remote_get()の詳細は以下のコーデックスをご覧頂きたいのですが、必要な部分だけ引用します。
GETメソッドを使用してHTTPリクエストからの生の応答を取得します。
今回の対象ファイルはテーマ内にあるため別ドメインではありませんが、後述する理由によりwp_remote_get()を使っています。
wp_remote_get()は配列で情報を取得しているので、ファイルと言いますか指定したURLの中身は以下の記述で取得できます。
$file = wp_remote_retrieve_body( $file_url );
wp_remote_retrieve_response_code()もそうですが、これはヘルパー関数と呼ばれるものです。
ヘルパー関数については、コーデックスの以下のページから説明文を引用します。
ヘルパー関数は HTTP API クラスを活用してプロセスを可能な限りシンプルにします。クラスやメソッドがコード処理の手助けになります。クラスを用いるためには、それで何をすべきか、それが何ができるかがわかっているという必要があります。
WordPress のコアなコードを修正するときには。ヘルパー関数を使う必要があります。API を用いる理由の1つとして、エラー確認の量を減らすとともに、バグが見つかった際に複数箇所を編集する必要がなくなるという効果があります。
ヘルパー関数を使わなくても以下の用に記述して動作させることはできますが、ヘルパー関数があるのなら使う方がよいと思います。
$file1 = wp_remote_get( $url . '/js/example.js');
$script = $file1['body'];
外部サービスのJSファイルもインライン化可能
wp_remote_get()を使うことで、外部のJSファイルのインライン化も可能です。
jsoonのように実行用関数と外部JSが分離している場合asyncもdeferも使えませんので、無理矢理インライン化して出力することでブラウザでのファイル取得動作をなくすことができます。
もっとも、こういうことが必要かどうかの検討がまず必要ですが。
他の方法の検討
PHPでファイルの中身を所得する場合は、以下の方法があります。
- file_get_contents()を使う
ただ、この方法はWordPressでは推奨されない模様です。詳細は以下のサイトに記載されています。
既に上記のページ内で紹介されていますが、WordPressの場合はWP_FileSystemを使う方法もあるようです。
ただ、個人的には通常のテンプレートタグ(といってよいのかわかりませんが)以外はあまり使いたくなかったので、今回はWP_FileSystemを含めて利用を諦めました。
なお、2008年の記事ですが、以下のような情報もありました。
上記ページの下部にあるWordPress用のコードを試してみましたが上手くいかず、しばらく触ってから諦めてしまいましたが。
以上のような経緯があり、半ば消去法に近い形ではありますがwp_remote_get()の利用を決めた次第です。
エラー処理なども簡易にできますし、安全に利用できるという点ではwp_remote_get()は魅力的なのですが、テーマ内のファイルを取得したいだけの場合にふさわしい仕組みなのかは自信がもてませんでした。
ファイルの種類をPHPにして対応する
出力時に文字列でさえあれば動作するのでCSSでもJSでも、ヒアドキュメントなどを使ってPHPファイルに記載しそのPHPファイルをget_template_part()で読み込んで出力すればすんなりと実現できます。
ただしその場合は、JSやCSSファイルをPHPファイルにしなければならず、既存のものをそのままインラインで利用する仕組みとは言えなかったため今回は除外しています。
結び
wp_remote_get()を使わずにもっとシンプルにできないかなと思いますが、現状ではこの辺りです。
テーマ内のファイルに限定した場合にはもっとふさわしい仕組みがあると思うのですが、なかなか見つからずでした。
計測ツールとPHPによるファイルの取得
当記事を全否定するようなことになりそうですが、wp_remote_get()であれ、PHPファイルにして読み込ませる方法であれ、以下のような計測結果を得ました。
- ChromeのWaterfallの Waiting と Content Download で計測
- PHPを使いサーバー側でファイルを取得して出力させる
- Waiting が100ms-200ms増える(ファイル数による)
- Content Download が増える(計測の度に変化が大きい/出力する内容による)
- PageSpeed Insights では、「サーバーの応答時間」で警告が出やすくなる
数値自体は計測方法で変わると思いますが、仕組み導入前後を比較した場合に導入後の方が数値が増加する点は計測できるかと思います。
つまり、PageSpeed Insightsのよう、ファーストビュー完成までの時間を重視された場合、サーバー側での処理が増えると警告が出やすくなります。
ページ全体としてファイルのリクエスト数まで見ているGTmetrixなどでは、ブラウザ側の作業量削減につながるため加点要因となり得ます(Waitingの時間は増えるため全体としては微妙だと思いますが)。
今回のインライン出力というのは、「ファイル取得作業などをサーバーで行い、モバイルなどの環境でクライアント側の負担を減らす」という意図があったのですが、そういう視点での工夫はよろしくないのだと実感しました。
補足
この記事の執筆自体は2016年12月でして、現在この仕組みは使っていません。
理由はいくつかありますが、やはりGoogleの評価が下がる可能性のある点は困るので、普通に外部ファイルでasyncやdeferを使う方が良いと判断しました。
補足2
2017年8月現在、当ブログにはいくつかCSSやJSのコード紹介があり、動作サンプルも設置していて、そこに対してこの仕組みを利用。
具体的には、is_single();でページを指定して、CSSやJSをそのページにだけインラインで出力させています。
0人がこの記事を評価
役に立ったよという方は上の「記事を評価する」ボタンをクリックしてもらえると嬉しいです。
連投防止のためにCookie使用。SNSへの投稿など他サービスとの連動は一切ありません。