【Astro/SSG】AstroでのJPEG/PNGからWebPへの一括画像変換

Astro / TailWind

Astroプロジェクトのpublicディレクトリ内の JPEG/PNGファイルを、ビルド時にWebPに変換して公開する

🚀 AstroでのJPEG/PNGからWebPへの変換手順

高性能な画像処理ライブラリである Sharp を使用し、Astroのビルド前フック(prebuild)で一括変換を行います。

ステップ 1: Sharpのインストール

まず、プロジェクトの依存関係として Sharp をインストールします。Bash

npm install sharp

ステップ 2: 変換スクリプトの作成

scriptsディレクトリを作成し、JPEG/PNGファイルをスキャンしてWebPに変換するNode.jsスクリプトを作成します。このスクリプトは、publicディレクトリ内の画像を見つけ、Astroの出力先(dist)内の対応する場所にWebPファイルを生成します。

例: scripts/optimize-webp.mjsJavaScript

import sharp from 'sharp';
import fs from 'fs/promises';
import path from 'path';

// Astroプロジェクトのルートディレクトリを取得
const rootDir = process.cwd();
const publicDir = path.join(rootDir, 'public');
const distDir = path.join(rootDir, 'dist'); // Astroの標準的なビルド出力先

/**
 * ディレクトリを再帰的にスキャンし、JPEG/PNGをWebPに変換する
 */
async function processDirectory(currentDir) {
  // publicディレクトリからの相対パス
  const relativePath = path.relative(publicDir, currentDir);
  
  // distディレクトリ内の対応する出力パス
  const outputDir = path.join(distDir, relativePath);

  try {
    const items = await fs.readdir(currentDir, { withFileTypes: true });

    for (const item of items) {
      const inputPath = path.join(currentDir, item.name);

      if (item.isDirectory()) {
        // サブディレクトリを再帰的に処理
        await processDirectory(inputPath);
      } else if (item.isFile() && /\.(jpe?g|png)$/i.test(item.name)) {
        
        // WebPのファイル名と出力パスを定義
        const webpFileName = item.name.replace(/\.(jpe?g|png)$/i, '.webp');
        const outputWebpPath = path.join(outputDir, webpFileName);

        // 出力先のディレクトリが存在しない場合は作成
        await fs.mkdir(path.dirname(outputWebpPath), { recursive: true });

        // Sharpを使ってWebPへ変換
        await sharp(inputPath)
          .webp({ quality: 80 }) // 変換品質を設定(80を推奨)
          .toFile(outputWebpPath);
        
        console.log(`✅ Converted: ${relativePath}/${item.name} -> ${path.relative(rootDir, outputWebpPath)}`);
      }
    }
  } catch (error) {
    console.error(`Error processing directory ${currentDir}:`, error.message);
  }
}

// publicディレクトリから処理を開始
console.log('--- Starting WebP Optimization ---');
processDirectory(publicDir)
  .then(() => console.log('--- WebP Optimization Complete ---'))
  .catch(err => console.error('FATAL ERROR:', err));

ステップ 3: ビルドスクリプトの更新

package.jsonを開き、Astroのビルドコマンド(astro build)の前に、作成したスクリプトを実行するフック(prebuild)を設定します。JSON

// package.json
"scripts": {
  "dev": "astro dev",
  "start": "astro start",
  "prebuild": "node scripts/optimize-webp.mjs", // 👈 これを追加
  "build": "astro build",
  "preview": "astro preview"
},

これで、npm run buildを実行すると、以下の流れで処理が行われます。

  1. npm run prebuildoptimize-webp.mjsが実行され、public内のJPEG/PNGがWebPに変換され、distディレクトリ内に配置されます。
  2. npm run build:Astroがビルドを実行し、元の画像ファイル(JPEG/PNG)とWebPファイルの両方がdistにコピーされます。

ステップ 4: HTMLでのフォールバック設定

最後に、WebPと元のJPEG/PNGを両方配信するために、HTMLテンプレート内で <picture>タグを使用します。

<picture>
  <source srcset="/images/your-image.webp" type="image/webp">
  
  <img src="/images/your-image.jpg" alt="画像の説明" width="800" height="600">
</picture>

これにより、すべてのブラウザで最適化された画像が配信されるようになります。

お気軽にコメントください!

スパム対応のためコメント認証に数日かかることがありますが、お気軽にコメントいただけると嬉しいです^^

コメント

タイトルとURLをコピーしました