WordPressをAWSのCDNサービスであるCloudFrontを使って高速化する際に、サイト多言語化対応プラグインであるqTranslate Xが原因でハマったので、解決方法などをメモする。
qTranslate XTへの乗り換え
WordPress多言語化対応プラグインであるqTranslate Xは2016年以降更新されておらずバグが多数残っている現状である。有志が立ち上げたプロジェクトであるqTranslate XTはバグ対応を含めてよくメンテナンスされているので乗り換えを行いましょう。ただし、qTranslate XTはWordpress管理画面のPlugin検索では出てこないためGithubから最新版をダウンロードしてインストールする。
すでに、qTranslate Xを利用している人は下記の手順で乗り換えを行いましょう
- qTranslate XTのGithubページからZip形式でコードをダウンロード
- 管理画面のプラグインの追加からZipファイルをアップロードしてインストール
- qTranslate XTを有効化
- この時点ではqTranslate XとqTranslate XTの両方が有効化されている状況です。両方とも同じ設定情報利用するらしく、片方で更新した変更がもう片方に反映されます。
- qTranslate Xを停止
- qTranslate Xを削除
設定のIntegration – Configuration Files に
./i18n-config.json
以外のゴミが入っていてエラーになっている場合は削除しましょう
qTranslate XTの設定
Detect Browser Languageの
Detect the language of the browser and redirect accordinglyをオフにします。
ブラウザのAccept-Languageヘッダーを元にサーバー側で判断するロジックですが、CDNからオリジンサーバーへAccept-Languageを透過させるとキャッシュ効率がわるくなるためオフにしましょう。ちなみにブラウザからサーバーへ渡されるAccept-Languageはenやjpといった2文字列だけではなく
en-US,en;q=0.9,ja;q=0.8,it;q=0.7,ko;q=0.6,fr;q=0.5,ru;q=0.4,zh-CN;q=0.3,zh;q=0.2
の様にブラウザごとにある程度複雑な文字列になっています。
WordPressのindex.php / admin.phpの改造
qTranslateではソースコード中で$_SERVER[‘HTTP_HOST’]を参照している箇所が存在します。これが悪さをしてCDN経由時におかしな挙動がおこります。
ブラウザ=>1=>CDN=>2=>Origin サーバー(実際にWordpressが動作しているサーバー)
とデータが流れる際に、1は実際にユーザーがブラウザに入力するドメイン名が用いられます。しかし、2でCDNからOrigin サーバーにデータを取得する際には、ユーザーは知ることのないOriginサーバーに割りあてたドメイン名を使ってアクセスします。しかしながら、qTranslateのコードが利用している$_SERVER[‘HTTP_HOST’]はユーザーは知ることのないOriginサーバーに割りあてたドメイン名を返すため挙動がおかしくなります。
そこで、Wordpressルートディレクトリにあるindex.php内に下記のコードを加えて、$_SERVER[‘HTTP_HOST’]を上書きしておきましょう
/** * Front to the WordPress application. This file doesn't do anything, but loads * wp-blog-header.php which does and tells WordPress to load the theme. * * @package WordPress */ /** * Tells WordPress to load the WordPress theme and output it. * * @var bool */ define('WP_USE_THEMES', true); /** Loads the WordPress Environment and Template */ require( dirname( __FILE__ ) . '/wp-blog-header.php' );
wp-admin/admin.phpの修正
同様に、コードの先頭にドメイン書き換えロジックを挿入します
<?php $domain_origin = "origin.domain.com"; $domain_for_public = "domain.com"; $_SERVER['HTTP_HOST'] = str_replace($domain_origin,$domain_for_public,$_SERVER['HTTP_HOST'] ); $_SERVER['SERVER_NAME'] = str_replace($domain_origin,$domain_for_public,$_SERVER['SERVER_NAME'] );
HTTPヘッダーのhostを転送することで解決
AWS CloudFrontの設定
WordPressのためのCloudFrontの設定を行います。下記0から2の項目はWordPressサイトをCloudFrontで配信するを参考に設定してください。管理画面や.phpコードがCDNキャッシュされないようになります。すべてのパターンにおいてHTTPヘッダーのhostを転送するようにしましょう。
3のDefault(*)の設定をqTranslateを考慮して行います。
設定内容は下記のとおりです。
Cookieのホワイトリストにqtrans_front_languageを設定してあげます。
CDN経由ではVisual Editorが表示されない問題を解決
CloudFrontからオリジンサーバーへアクセスする際のUser-agentは「Amazon CloudFront」になるため、User-agentで処理を分岐しているコードがおかしな挙動になります。Visual EditorはEnable Visual Mode in CloudFrontプラグインを入れることでCloudFront利用時でも正常に表示されるようになります。
OriginサーバーをクローラーにIndexされないようにする
CDNを利用すると、CDNに割り当てたドメイン、Originサーバーに割り当てたドメインのどちらのURLでも同じコンテンツにアクセスできることになりSEO上よくありません。Originサーバーがサーチエンジンにクロールされないようにしましょう。
まず、Originサーバーに設置したrobots.txtにクローラー拒否の記述を行います
User-agent: * Disallow: /
つぎに、CDNのrobots.txtにアクセスが有った場合に、別途S3に配置したrobots.txtを表示するように設定します。こちらの回答を参考にしています。
1) S3のBacketを作成し、robots.txtだけを配置します。その際、Publicに設定しブラウザからアクセスできるようにしておきます。内容は下記のようにします
User-agent: * Disallow: /wp-admin/ Allow: /wp-admin/admin-ajax.php
2) CloudFrontのDistribution settingsでCreate originで1で作ったBacketを指定します
3) CloudFrontのBehaviorを作成し、下記の通り設定します
Path Pattern: robots.txt
Origin: 2で作成したOrigin
4) 3で作成したBehaviorのPrecedenceを0に設定します。
5) Invaridationで、/robots.txt を指定してCDNのキャッシュをクリアします
投稿時にCDNキャッシュをクリアする
記事投稿・更新時に、CloudFrontのキャッシュをPurge(Invaridate)するには、CloudFront Clear Cacheプラグインを利用します。記事を更新した場合、該当記事のキャッシュが自動的に削除されます。
追記(2019/03/19)
ログアウト時のクッキー削除。Wordpressでは一度管理者などでログインするとログアウトしても一部のクッキーが残ったままになり、CDNのキャッシュに影響を及ぼします。Logout Clear Cookiesプラグインをインストールしてログアウト時にクッキーを削除するようにしましょう。