[続報] fopen,file_get_content等がそのままでは利用できないサーバーでWordPressのjQueryをCDNにする方法

最近、うちのlinux mintのChromiumがやたら重いので、あぁもう鬱陶しいと思っていた所、Firefoxのアップデートが先日来まして、バージョンが39.0.3になりました。これだけ重いChromiumを使い続ける意味もなく、どうせ重いならFirefoxにした方が良いかもと、Firefoxを立ち上げてみたんですよ。

あらまぁビックリ、奥さんすごく軽くってよ

って感じでした。

特に、ブラウザ終了後シャットダウンメニューを出すまでの間、そりゃChromiumの時はだいぶ待ったさって感じだったんですが、Firefoxだとブラウザ終了直後というと言い過ぎですけれども、ほぼそれぐらいで終了ボタンが押せるわけですよ。何やってんだよChromiumって事でしばらくFirefoxにすることにしました。

で、Firefoxにしたのはいいんですが、今までたいして確認していなかったと言うのもあって、このブログを見ていると、あれ?jQuery読めてるのにjQuery is not definedが出てたんですよね。Chromiumでもたまには出てたんですが、おかしい・・・と思いまして、色々と調査しておりました。

まずは、WordpressでjQueryを読み込んでいるwp_enqueue_scriptあたりを見てたんですけど、headタグを見ても、jQueryはちゃんと表示されているし、ローカルに保存してある方を読み込んでも、きちんとアドレスも間違いなく読み込めているわけです。しかし、エラーが出てる。どうなったんだよFirefoxと思いつつ、更なる調査をしていた所、wp_remote_get()と言うのを見つけたんです。

codexを見ると、

GETメソッドを使用してHTTPリクエストからの生の応答を取得します。
結果は、HTTPヘッダとコンテンツが含まれています。

お?もしかして、file_get_contentsの代わりになるのか?と思って、早速以前書いた「fopen,file_get_content等がそのままでは利用できないサーバーでWordPressのjQueryをCDNにする方法」のスクリプトを変更してみました。
以前の記事は以下になります。

fopen,file_get_content等がそのままでは利用できないサーバーでWordpressのjQueryをCDNにする方法
※ fopen,file_get_contentが利用できるサーバーでも下記で動作します。←これ重要 ※ 内容的にはwordpressのj...

2015/08/10 修正版スクリプト

前提として、GoogleCDNのjQueryが読めなかった場合のフォールバックのため、Simplicity-child/lib/にjquery.min.jsとして2.1.4版が保存してあると言うのを先に書いておきます。
基本Simplicity用に書いてますが、読みかえたり応用すればどのテーマでもイケるんじゃなかろうかと思います(※すでにenqueueされていたりで解除したりするのはテーマごとにハンドル名などが異なったりするので調査する必要があります)。

またこれらのスクリプトは子テーマfunctions.phpに追記します。

以前は、file_check関数を作り、cUrlでアクセスして、その応答によってCDNを読み込ませるかローカルにするかを条件分岐していたのですが、wp_remote_getが利用できるならそっちのが(速度とかではなく手順として)速いのではないかと思ったりもして、やってみた所、いけるんですよね、これが。で、返ってきた内容は、

このようなものが入って返ってきます。しかし、ここからhttpレスポンスコードをどうやって出そうかと思っていた所、wp_remote_retrieve_response_code()というのがあるのがわかったので早速テストしてみた所、レスポンスコードを返すわけです。そしたら簡単じゃんって事で今回の形に相成りました。

add_filterでjqueryにasyncやdeferを付けられるのですが、asyncにするとどうもエラーが出るようだったのでdeferに修正しています。これでFirefoxでも問題なくいけるようになったのではないかなぁと思ったり。

ついでにFontAwesomeも

これも前提として、フォールバックのためにSimplicity-child/lib/にfont-awesome.min.cssとして保存してあるとします。
親テーマのheader-css.phpにて、スタイルシートを読み込んであるので、予め該当部分をコメントアウトしておきます。PHPのタグで囲んで/**/などでいけます。
わいひらさん曰く、テーマチェッカーなどにかけた場合、CDNを読み込んでいるとポイントが下がるということで、せっかく満点もらっているからCDNでポイントを下げたくないという意向があってローカルファイルを読み込んでいるそうです。
ただしかし、実際にはCDNで読み込む方が何かとメリットがある場合が多いのと、最悪、読み込めなかった場合のフォールバックもしてあるので以下のような感じで良いかと思います。

特に、常に親テーマのアップデートを行える環境にない方(つまりは僕ですけど)や、ある程度のアップデートまでは細かな更新はしないと言う方などで、fontAwesomeが常に最新版と言うわけではない人には有効な方法ではないでしょうか?

※ 2015/08/17修正 !===200の部分が間違っていたので直しました。

スポンサーリンク

シェアする

フォローする

コメント

  1. がちょぴん より:

    HIDEKICHIさん

    ご返答ありがとうございます。
    私は色々と考え過ぎですね。

    >お問い合わせフォームから詳細な事お話ししたかったのですが一部お話しします。
    日本語おかしいので訂正しますと、下記の発言になります。
    「お問い合わせフォームから詳細な事お話ししたかったのですが、お問い合わせフォーム見当たらないので一部お話しします。」になります。

    >jQueryを利用するスクリプトはjQueryが無いと動きませんよね?
    確かにそうですね。

    >これをフォールバックと言います。
    他の例え方は、システムなどに障害が起きた時、代替のシステムに変更(有効)するという事ですね。

  2. がちょぴん より:

    HIDEKICHIさん

    ご返答ありがとうございます。

    なるほどです。
    HIDEKICHIさんのご返答を簡潔にすると、
    file_check関数でCDNからjQueryがDLできるか確認。
    コードが200になったらCDNからjQueryをDLしてくる。
    200以外の数字で読み込めない場合はローカルからjQueryをDLしてくる。

    お問い合わせフォームから詳細な事お話ししたかったのですが一部お話しします。
    CDNからjQueryをDLした場合、jQueryが含まれるプラグイン側もCDNのjQueryに変わるという事でしょうか?
    プラグイン側もCDNのjQueryに変わって、CDNがダウンしてもローカルのjQueryに変わるので動作は変わらないですという事であれば私の考え過ぎです。

    また、時間を作ってHIDEKICHIさんのコメントを何回も読むようにします。

    • hidekichi より:

      >jQueryが含まれるプラグイン側もCDNのjQueryに変わるという事でしょうか?

      この部分の意味がいまいち僕が理解できてないかも知れませんが、jQueryを利用するスクリプトはjQueryが無いと動きませんよね?
      そのjQueryをどこから読み込んでいるかというだけのことなんですよ。なので、jQueryを利用しているその他の、いわゆるjQueryプラグインというものはどれも動作すると思います。

      jQueryをCDNから読み込むようにしておくと、CDNが万が一ダウンした場合、jQueryプラグインは動作することができず「jQueryがないぜ」と言うエラーを吐きます。なのでローカルのjQueryを予め用意しておいて万が一に備えるというものです。これをフォールバックと言います。

      >CDNがダウンしてもローカルのjQueryに変わるので動作は変わらないですという事であれば

      まさにこれですね(笑)

  3. がちょぴん より:

    HIDEKICHIさん

    ご返答ありがとうございます。
    こっそり・静かに・密やかにフォーラムの投稿見てます…

    「get_template_directory_uri()」←なるほどです。
    ググったりCODEX等で調べて、ふむふむしたいと思います。
    スラッシュの件まで細かく教えてくれてありがとうございます。
    jquery.min.js なければDLして引っこ抜いて保存しておきます。

    開発者ではないので全く無知なのにそういう事聞けるの?と突っ込みされると思いますが、
    @fopen関数ではなくHIDEKICHIさんが記述したfile_check関数というものでCDNからjQueryがDLできるか確認するんですよね…?
    あと、HIDEKICHIさんが記述したコードってキャッシュ(WPから出力されたページキャッシュ)にも対応しているんでしょうか?
    何らかの原因でCDNがダウン(障害)して復旧の間に、キャッシュが更新されなかったらユーザーはjQueryをDLできなくなる可能性があるのかな?思ってます…
    と聞いても、○行のコードがこうでここがこういう事と言われましても、チンプンカンプン意味くじピーマンわけワカメちゃんになると思います…(じゃ、聞くなよ!)
    HIDEKICHIさんが心の中で思っている事「全く無知というか流れ的な事分かってるじゃんw 全く無知ならそんな質問できないと思うし…がちょぴんさって何者なんだろうw」って勝手に心読んでしまいました…

    子テーマの仕組み既に把握しているのですが、それにも関わらず地獄を味わいたいのか分かりませんが親テーマで頑張ってます…!
    親テーマのスタイルから子テーマに呼び出す方法(functions.php)も分かっているので多分恐らくなんとなく、なんくるないさーで大丈夫です。

    • hidekichi より:

      >@fopen関数ではなくHIDEKICHIさんが記述したfile_check関数というものでCDNからjQueryがDLできるか確認するんですよね…?
      大まかに言うとそういう感じです。実際の所は、wordpressの関数のwp_remote_get( $url, $args );で取得した内容から、wp_remote_retrieve_response_code($test_url);にて、httpのステータスコードを調べて、そのコードが200、つまりOKと言うか、問題なしとなった時にはCDNから登録します。ここが200以外になった場合は、ローカルのjQueryを登録します。世に言うフォールバックの部分です。
      登録するというのは、wordpressにjqueryはCDNあるいはローカルの・・・と報告しておいて(wp_register_script())、wp_enqueue_script()にて、読み込み順番待ちの列に加えると言う感じです。

      wp_enqueue_script()では、各々のスクリプトの依存関係を調べられます。jQueryが必要なファイルはjQueryの後に並ぶというような感じです。整列が済んだら、headあるいはfooter付近に順番に読み込まれます。つまり、htmlのリンクタグとして書き出されるわけです。ブラウザはその情報を見てタグの中身のアドレスからjQueryを読み込みます。

      キャッシュについては、CDN自体が既にキャッシュファイルなので、気にすることはないのではなかろうかと思います。ハードディスクから読み込みよりもCDNから読み込む方が速かったりすることもあります。基本的にjQueryはjavascriptなので、参照先が同じアドレスのスクリプトの場合は、ブラウザにもよりけりかと思いますがキッシュしているんではなかろうかと思います。ここらは参照先がどこであろうと、キャッシュが無ければ、参照先のアドレスから拾ってくるでしょうし、そうでない場合はキャッシュからと何も特別なものではないかと思います。

      このコードの意味合い的には、CDNがダウンしていたりした場合に備えてローカルのファイルも用意しておき、かつWordpressが元々自前で持っているファイルを使わないと言うのが目的となってます。またログインしないと見れない画面はwordpress自前のjQueryを利用します。

      結果的にこのコードで何が変わるかといえば、ウチの場合はheadでjQueryやらを読み込んでいますが、その内容だけです。つまりはサーバーで処理している部分の話なので、htmlに書きだされた結果をブラウザは処理しており、そのhead内のスクリプトの記述による動作はブラウザの通常の動作と何ら変わりません。

      簡単に言うと、

  4. がちょぴん より:

    先程コメントしましたが、
    コメントする記事間違えましたので、
    先程のコメントを削除お願い致します!><
    ——————————————————–
    は…は…初めまして…

    開発者ではないので全く無知ですが、
    コード 25行目にあるディレクトリ変更すれば、他のテーマでも利用できますね!
    子テーマ利用していない場合は、直接親テーマでも全然利用できるという事ですよね…?

    • hidekichi より:

      改めて、どうも、はじめまして(笑)

      ディレクトリが
      $local_url = get_stylesheet_directory_uri() . “/lib/jquery.min.js”;

      ↑これなら、子テーマの/lib/jquery.min.jsになります。親テーマの場合はget_stylesheet_directory_uri()ではなく、get_template_directory_uri()に変更すれば、親テーマのlib/jquery.min.jsって事になります。

      get_stylesheet_directory_uri()もget_template_directory_uri()も取得するアドレスの最後にスラッシュが入ってないと思うので、/lib/jquery.min.jsとスラッシュをお忘れなく。またlibディレクトリを変更すれば任意のディレクトリのjquery.min.jsと言うことになります。

      jquery.min.jsは予め公式などからダウンロードしておく必要があります。

      Simplicityに関係する部分というと、これらのlibフォルダがあるかどうかぐらいの話で、別に他のテーマでも使えると思います。libが無ければ作ればよいだけですし、何かしら都合の良いディレクトリがあればそれでもOKです。

      やってることはCDNが失敗した時に/lib/の中のjquery.min.jsを読みに行くと言うことなので、任意のディレクトリを指定することはもちろん可能です。

      親テーマに直接書く場合でもいけると思うんですけど、ダメだった場合は、元々のwp_enqueue_scriptでjQueryを読み込んでいるあたりをコメントアウトしておけば良いかも知れません。

      記事の関数内では、jQueryを一旦wp_deregisterして登録解除してから新たにCDNの方(読めなかった場合はローカルファイル)で登録しなおしているので、必要ないとは思うんですけどね。

      またSimplicityに限らず親テーマは何かしらにつけてアップデートされる場合もあるので、子テーマの利用をオススメします。

      親テーマのfunctions.phpあたりの記述の内容にもよりけりですが、基本css部分先頭の/**/の中の記述で親テーマと子テーマは読み分けていたりするだけなので、ちょっと手を加えるだけで子テーマを作ることは可能です。

  5. 堂本一郎 より:

    堂本一郎と申します。simplicityのフォーラムで「アイキャッチ画像が表示されません。」に
    回答いただいた者です。
    わいひらさんの説明文で「サーバーのphp.iniのallow_url_fopenがOffの時は外部サーバーから画像を取得できない可能性があります。」とありますが、サーバーのphp.ini とは、レンタルサーバーにあるのですか?また、allow_url_fopenをONにすれば、外部サーバーから画像を取得できるのですか?
    よろしくお願いいたします。

    • hidekichi より:

      >サーバーのphp.ini とは、レンタルサーバーにあるのですか?

      わかりやすくWindowsでいうと、サーバーがwindowsでphpはwordやexcelみたいなソフト、php.iniはそれらソフトの設定ファイルです。
      一般的には、サーバーはapacheで、そのモジュールがPHPとなります。モジュールとはApache API仕様に従って記述されたコードを言います。つまりは、apacheの装置って感じでしょうか。機能と言っても良いかも知れません。まぁCGI版もあるのでアレなんですけども。
      webサイトはサーバーに何かしら送るとその返答があって何かしらを表示したりします。そういった時にPHPのスクリプトを利用する場合はapacheにPHPがインストールされている必要があり、そのPHPの動作の仕組みを書いてあるのがphp.iniです。なのでサーバー上にあると言うことになります。どこにあるかは、

      < ?php phpinfo(); ?>

      < の後にスペースが入ってるかも知れませんが、スペースはいりません。いわゆるPHPの一般的な書き方でその中に、phpinfo();とだけ書いておきます。

      とだけ書いたファイル、例えばtest.phpとかと言うファイル名で保存したファイルを任意のディレクトリにアップロードして、そのアドレスにアクセスするとphpinfoと言うPHPの仕様書みたいのが表示されます。そこのloaded Configuration File (php.ini) Pathあたりに、php.iniのありかが記載されているかと思います。
      自分でサーバーを運営している場合はアクセスもできるかと思いますが、そこに勝手にアクセスされると色々マズイのでたいていはコントロールパネルみたいのが用意されていて、そこから触れるようになっていたりします。それも無い場合は書き換えることはできないと考えても良いかも知れません。スクリプト的にイケたりする場合もあるんですけれども、触って欲しくないから触れないようにしてあると理解する方がスマートです。

      >allow_url_fopenをONにすれば、外部サーバーから画像を取得できるのですか?

      allow_url_fopenとは、phpのfopen関数、つまりファイルを読み込むコマンドで、urlとあるように、アドレス先のファイルを読み込むと言う事を許可するかどうかと言う感じの設定です。これは通常利用の場合は特に問題無さそうですが、サーバーの管理をする上で、どの外部ファイルでも読み込めるような仕組みを作ると、ファイルを読み書きする権限が管理者以外だった場合(ハッキングされたりウイルス感染とか)に、エラいことになりかねません。
      なので、allow_url_fopenはセキュリティ的な理由からoffにするサーバーもしばしばあったりするわけです。もちろんのこと、これをONにすると、リモート(url先にある)ファイルを読み込むことができますから画像を取得することができます。例) file_get_contents(アドレス/image.jpg)など。

      しかし、仮にallow_url_fopenがoffであった場合でも、cURL(Client URL Library)と言う別の機能が利用できる場合もあり、そこで外部の画像を取得することは可能だったりすることもあります。