2026年10月8日
2026年10月8日
WordPressのCDNエラーを解決する方法
はじめに
WordPressにCDNを設定したのにブラウザのネットワークタブで確認するとオリジンサーバーから直接配信されている・CDN導入後に管理画面のログインがループする・CloudflareのProxy機能を有効にするとWordPressの画像が混在コンテンツ(Mixed Content)エラーになる・Amazon CloudFrontを設定したがwp-login.phpやwp-adminがキャッシュされてログインできなくなったといった問題は、CDNのURL書き換え設定の不備・HTTPSとHTTPの混在・キャッシュ除外ルールの設定漏れが原因です。
症状・原因
- CDN設定後にサイトのCSSやJavaScriptが読み込まれずデザインが崩れる
wp-adminやwp-login.phpへのアクセスがCDNにキャッシュされてログインできない- Cloudflare経由でアクセスするとHTTPSなのにブラウザが「安全でない」と表示する
- CDNのURLに書き換わらず画像が元のサーバーから配信され続けている
解決手順
ステップ1:CDNの設定状態を診断する
# WP-CLIでサイトURLとCDN設定を確認
wp eval "
echo 'siteurl: ' . get_option('siteurl') . PHP_EOL;
echo 'home: ' . get_option('home') . PHP_EOL;
echo 'WP_CONTENT_URL: ' . WP_CONTENT_URL . PHP_EOL;
// アップロードURLの確認
\$uploads = wp_upload_dir();
echo 'Upload URL: ' . \$uploads['baseurl'] . PHP_EOL;
"
# 静的ファイルのレスポンスヘッダーを確認
wp eval "
\$response = wp_remote_get(get_theme_file_uri('style.css'), ['sslverify' => false]);
if (!is_wp_error(\$response)) {
\$headers = wp_remote_retrieve_headers(\$response);
echo 'CF-Cache-Status: ' . (\$headers['cf-cache-status'] ?? 'none') . PHP_EOL;
echo 'X-Cache: ' . (\$headers['x-cache'] ?? 'none') . PHP_EOL;
echo 'Via: ' . (\$headers['via'] ?? 'none') . PHP_EOL;
echo 'Content-Encoding: ' . (\$headers['content-encoding'] ?? 'none') . PHP_EOL;
}
"
# HTTPS混在コンテンツを確認
wp eval "
global \$wpdb;
\$http_urls = \$wpdb->get_var(
\"SELECT COUNT(*) FROM {\$wpdb->posts}
WHERE post_content LIKE '%http://%'
AND post_status = 'publish'\"
);
echo 'HTTP URL in posts: ' . \$http_urls . PHP_EOL;
"
ステップ2:WordPressのURLをCDNに書き換える
// wp-config.php: CDN URLを設定
define('WP_CONTENT_URL', 'https://cdn.example.com/wp-content');
// または functions.php でフィルターを使う方法
add_filter('wp_get_attachment_url', 'replace_with_cdn_url');
add_filter('the_content', 'replace_with_cdn_url');
add_filter('script_loader_src', 'replace_with_cdn_url');
add_filter('style_loader_src', 'replace_with_cdn_url');
function replace_with_cdn_url(string $url): string {
$site_url = get_option('siteurl');
$cdn_url = 'https://cdn.example.com'; // CDNのURL
// 管理画面では置換しない
if (is_admin()) {
return $url;
}
return str_replace($site_url, $cdn_url, $url);
}
# Mixed Content(HTTP/HTTPS混在)を一括修正
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' \
--all-tables \
--skip-columns=guid
# CDN URLに一括書き換え(メディアライブラリのURL)
wp eval "
\$uploads = wp_upload_dir();
echo 'Checking upload URLs...' . PHP_EOL;
\$atts = get_posts(['post_type' => 'attachment', 'posts_per_page' => 5]);
foreach (\$atts as \$a) {
echo wp_get_attachment_url(\$a->ID) . PHP_EOL;
}
"
ステップ3:Cloudflareの設定を最適化する
// functions.php: Cloudflare対応設定
// ① Cloudflare経由のIPアドレスを正しく取得
add_action('init', function(): void {
if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) {
$_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_CF_CONNECTING_IP'];
}
});
// ② CloudflareのHTTPSをWordPressに認識させる
add_action('init', function(): void {
if (
isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'
) {
$_SERVER['HTTPS'] = 'on';
}
// Cloudflare Flexible SSL(オリジンはHTTP)の場合
if (isset($_SERVER['HTTP_CF_VISITOR'])) {
$cf_visitor = json_decode($_SERVER['HTTP_CF_VISITOR'], true);
if (isset($cf_visitor['scheme']) && $cf_visitor['scheme'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
}
});
# .htaccess: Cloudflare対応(wp-config.phpの前に追加)
# HTTPS判定をCloudflareのヘッダーから取得
SetEnvIf X-Forwarded-Proto "https" HTTPS=on
// wp-config.php: プロキシ経由のHTTPS設定
// Cloudflare・ロードバランサー対応
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
define('FORCE_SSL_ADMIN', true);
ステップ4:CDNのキャッシュ除外ルールを設定する
// functions.php: CDNキャッシュをWordPressのフックで制御
// ① 投稿更新時にCDNキャッシュをパージ
add_action('save_post', function(int $post_id): void {
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
$permalink = get_permalink($post_id);
// CloudflareのCache Purge API
$cf_zone_id = defined('CF_ZONE_ID') ? CF_ZONE_ID : '';
$cf_api_key = defined('CF_API_KEY') ? CF_API_KEY : '';
if ($cf_zone_id && $cf_api_key) {
wp_remote_post(
"https://api.cloudflare.com/client/v4/zones/{$cf_zone_id}/purge_cache",
[
'headers' => [
'Authorization' => "Bearer {$cf_api_key}",
'Content-Type' => 'application/json',
],
'body' => wp_json_encode(['files' => [$permalink]]),
]
);
}
});
// ② 動的ページにCache-Controlヘッダーを設定
add_action('send_headers', function(): void {
// ログインユーザーやカート/チェックアウトページはキャッシュしない
if (is_user_logged_in() || is_cart() || is_checkout()) {
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Surrogate-Control: no-store'); // CDNへの指示
return;
}
// 静的なアーカイブページは1時間キャッシュ
if (is_archive() || is_home()) {
header('Cache-Control: public, max-age=3600, s-maxage=86400');
return;
}
// 個別投稿は10分キャッシュ
if (is_singular()) {
header('Cache-Control: public, max-age=600, s-maxage=3600');
}
});
ステップ5:CDNのパフォーマンスを検証・最適化する
# CDNからの配信を確認(curlでヘッダーを取得)
wp eval "
\$test_urls = [
get_theme_file_uri('style.css'),
content_url('/uploads/2024/01/sample.jpg'),
];
foreach (\$test_urls as \$url) {
\$response = wp_remote_head(\$url, ['sslverify' => false]);
if (!is_wp_error(\$response)) {
\$headers = wp_remote_retrieve_headers(\$response);
echo \$url . PHP_EOL;
echo ' CF-Cache: ' . (\$headers['cf-cache-status'] ?? 'N/A') . PHP_EOL;
echo ' Cache-Control: ' . (\$headers['cache-control'] ?? 'N/A') . PHP_EOL;
echo ' Age: ' . (\$headers['age'] ?? '0') . ' sec' . PHP_EOL;
}
}
"
// functions.php: CDN経由の場合のみリソースURLを最適化
add_filter('wp_resource_hints', function(array $hints, string $relation_type): array {
$cdn_domain = 'cdn.example.com';
if ($relation_type === 'preconnect') {
$hints[] = ['href' => "https://{$cdn_domain}"];
}
if ($relation_type === 'dns-prefetch') {
$hints[] = ['href' => "//{$cdn_domain}"];
}
return $hints;
}, 10, 2);
注意事項
- Cloudflareの「Full (strict)」SSLモードを使用する場合、オリジンサーバーにも有効なSSL証明書が必要です。「Flexible」モードではオリジンはHTTPのままですが、WordPressがHTTPSリクエストとして認識しないためログインループが発生することがあります
- CDN URLに書き換えたあとはプラグインの設定画面に保存されているURLも変わる可能性があります。バックアップを取ってから変更してください
wp-login.php・wp-cron.php・wp-admin/・xmlrpc.phpは必ずCDNのキャッシュ除外ルールに追加してください。キャッシュされるとサイトが正常に動作しなくなります
まとめ
WordPressCDNエラーの解決は①レスポンスヘッダーのCF-Cache-Status/X-Cache確認・wp_upload_dir()でアップロードURLチェック・HTTP混在コンテンツのカウント、②WP_CONTENT_URL定数またはフィルターで静的ファイルURLをCDNに書き換え・wp search-replaceでHTTP→HTTPS一括変換、③HTTP_CF_CONNECTING_IPでIPアドレス取得・HTTP_X_FORWARDED_PROTOでHTTPS認識・FORCE_SSL_ADMIN=trueで管理画面をHTTPS強制、④Cloudflare API経由の投稿更新時キャッシュパージ・send_headersフックで動的ページにCache-Control: no-store・静的コンテンツに適切なs-maxage設定、⑤wp_resource_hintsでCDNドメインへのpreconnect・dns-prefetch追加・レスポンスヘッダーでCDN配信を確認の手順で解決します。