2026年10月28日

2026年10月28日

WordPress画像をWebPに変換して最適化する方法

はじめに

「PageSpeed InsightsでWebP形式で画像を配信してください、と指摘された」「画像ファイルサイズが大きくてページの読み込みが遅い」——WebPに変換するだけで画像ファイルサイズを平均25〜35%削減でき、Core Web VitalsのLCPスコアが改善します。

症状・原因

JPEGやPNGはWebPより大幅にファイルサイズが大きく、ページ速度を低下させます。WordPress 5.8以降はWebPのアップロードとアイキャッチ画像への自動変換に対応していますが、既存画像の変換と配信の最適化には追加設定が必要です。

解決手順

ステップ1:WordPress 5.8以降のWebP標準機能を確認する

// WordPress 5.8以降、WebPをメディアライブラリにアップロード可能
// 5.8+: WebPファイルのアップロードが許可される
// 6.1+: JPEG/PNGアップロード時にWebP版を自動生成(サブサイズとして)

// WebP自動生成が有効かどうかを確認
$quality = apply_filters( 'wp_editor_set_quality', 82, 'image/webp' );
// デフォルト品質: 82(0-100、高いほど高品質・大きいサイズ)

// WebPの品質を調整
add_filter( 'wp_editor_set_quality', function( $quality, $mime_type ) {
    if ( 'image/webp' === $mime_type ) {
        return 80; // 品質を80に設定
    }
    return $quality;
}, 10, 2 );

// WebP変換が対応しているか確認
function supports_webp() {
    if ( ! class_exists( 'Imagick' ) ) return false;

    $imagick = new Imagick();
    $formats = $imagick->queryFormats( 'WEBP' );
    return in_array( 'WEBP', $formats, true );
}

ステップ2:.htaccessでWebPを自動配信する

# .htaccess: WebP対応ブラウザにWebPを自動配信
# JPGやPNGのリクエストに対してWebP版が存在すれば自動的に返す

<IfModule mod_rewrite.c>
    RewriteEngine On

    # ブラウザがWebPをサポートしているか確認
    RewriteCond %{HTTP_ACCEPT} image/webp

    # WebP版ファイルが存在するか確認(.jpg.webp または .png.webp)
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.webp -f

    # WebPにリライト(ヘッダーも変更)
    RewriteRule ^(.+)\.(jpe?g|png)$ $1.$2.webp [T=image/webp,L]
</IfModule>

<IfModule mod_headers.c>
    # Varyヘッダーを追加(CDNキャッシュがWebP/非WebPを区別できるように)
    <FilesMatch "\.(jpe?g|png)$">
        Header append Vary Accept
    </FilesMatch>
</IfModule>

# WebPのMIMEタイプを追加
<IfModule mod_mime.c>
    AddType image/webp .webp
</IfModule>

ステップ3:ImagickでWebPを生成するPHPコードを書く

// functions.php: 画像アップロード時にWebPを自動生成
add_filter( 'wp_generate_attachment_metadata', function( $metadata, $attachment_id ) {
    $file      = get_attached_file( $attachment_id );
    $mime_type = get_post_mime_type( $attachment_id );

    // JPEG/PNGのみWebPを生成
    if ( ! in_array( $mime_type, [ 'image/jpeg', 'image/png' ], true ) ) {
        return $metadata;
    }

    if ( ! class_exists( 'Imagick' ) ) return $metadata;

    try {
        // オリジナルファイルをWebPに変換
        $imagick = new Imagick( $file );
        $imagick->setImageFormat( 'webp' );
        $imagick->setImageCompressionQuality( 80 );
        $imagick->writeImage( $file . '.webp' );
        $imagick->destroy();

        // サブサイズも変換
        $upload_dir = dirname( $file );
        foreach ( $metadata['sizes'] as $size => $size_data ) {
            $size_file = $upload_dir . '/' . $size_data['file'];
            if ( file_exists( $size_file ) ) {
                $img = new Imagick( $size_file );
                $img->setImageFormat( 'webp' );
                $img->setImageCompressionQuality( 80 );
                $img->writeImage( $size_file . '.webp' );
                $img->destroy();
            }
        }
    } catch ( Exception $e ) {
        // Imagickエラーは無視(WebPなしで続行)
    }

    return $metadata;
}, 10, 2 );

ステップ4:picture要素でWebPとフォールバックを両立する

// functions.php: picture要素でWebPを配信する関数
function get_picture_with_webp( $attachment_id, $size = 'large', $attrs = [] ) {
    $image_url  = wp_get_attachment_image_url( $attachment_id, $size );
    $image_meta = wp_get_attachment_metadata( $attachment_id );
    $webp_url   = $image_url . '.webp';
    $alt        = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );
    $class      = isset( $attrs['class'] ) ? esc_attr( $attrs['class'] ) : '';
    $loading    = isset( $attrs['loading'] ) ? esc_attr( $attrs['loading'] ) : 'lazy';

    // WebPファイルの存在確認
    $upload_dir  = wp_upload_dir();
    $image_path  = str_replace( $upload_dir['baseurl'], $upload_dir['basedir'], $image_url );
    $webp_exists = file_exists( $image_path . '.webp' );

    if ( $webp_exists ) {
        return sprintf(
            '<picture>
                <source type="image/webp" srcset="%s">
                <img src="%s" alt="%s" class="%s" loading="%s" decoding="async">
            </picture>',
            esc_url( $webp_url ),
            esc_url( $image_url ),
            esc_attr( $alt ),
            $class,
            $loading
        );
    }

    // WebPがない場合は通常の画像を返す
    return wp_get_attachment_image( $attachment_id, $size, false, $attrs );
}
// テンプレートでの使用例
<?php if ( has_post_thumbnail() ) : ?>
    <?php echo get_picture_with_webp( get_post_thumbnail_id(), 'large', [
        'class'   => 'hero-image',
        'loading' => 'eager', // LCP画像はeagerで
    ] ); ?>
<?php endif; ?>

ステップ5:プラグインで既存画像を一括WebP変換する

【WebP変換プラグインの比較】

1. ShortPixel Image Optimizer(推奨)
   - 自動WebP変換 + 画像圧縮
   - 月100枚まで無料
   - .htaccss設定を自動で行う
   - 既存画像の一括変換: ShortPixel → Bulk Process

2. Imagify
   - WebP変換 + lossless/lossy圧縮
   - 月25MBまで無料
   - WP Rocketとの連携が優れている

3. WebP Express(無料)
   - ローカルでWebP変換(APIキー不要)
   - Imagickまたはcwebpが必要
   - .htaccessで自動配信設定を代行

4. Converter for Media(無料)
   - WebP/AVIF変換に対応
   - picture要素またはHTTP 301リダイレクトで配信

【手動でcwebpコマンドを使う場合(VPS/専用サーバー)】
# 単一ファイルを変換
cwebp -q 80 input.jpg -o output.webp

# ディレクトリ内の全JPGを変換
find wp-content/uploads -name "*.jpg" -exec sh -c \
  'cwebp -q 80 "$1" -o "${1%.jpg}.jpg.webp"' _ {} \;

注意事項

  • WordPress 6.1以降はJPEG/PNGアップロード時にWebPのサブサイズを自動生成しますが、この機能はサーバーにImagickまたはGDがWebP対応でインストールされている必要があります。
  • .htaccessリライトルールでWebPを配信する場合、CDNを使っている場合はCDNの設定でVary: Acceptヘッダーを尊重するように設定が必要です。CloudflareはデフォルトでVaryヘッダーを無視する場合があります。
  • AVIFはWebPよりさらに高圧縮ですが、ブラウザ対応はWebPより若干劣ります。picture要素で→→のフォールバックチェーンを構成するのが理想です。

まとめ

WebP最適化は「WordPress 6.1+の自動WebP生成を確認→.htaccessでWebP対応ブラウザに自動配信→ImagickフックでアップロードごとにWebP生成→picture要素でフォールバック対応→ShortPixelで既存画像を一括変換」の流れで整備します。関連記事:WordPressで画像の遅延読み込みを設定する方法、WordPressのGZIP圧縮を設定してページ速度を改善する方法。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲