サイト生成ツール、フレームワーク、CMS

WordPress などの CMS やその他のサイト生成ツールを使用すると、レスポンシブな画像を簡単に使用できます。

各画像の代替カットを手動で保存し、Squoosh.app などのツールを使用して手動で最適化するよりもはるかに改善されますが、開発プロセスの 1 つのステップとして画像圧縮を自動化することには、いくつかの制限があります。1 つ目は、サイト全体で使用される画像を常に完全に制御できるわけではないことです。ウェブ上にあるほとんどのユーザー向けの画像は、開発上の懸念事項ではなく、ユーザーまたは編集者によってアップロードされたコンテンツに関する懸念です。JavaScript やスタイルシートなどの開発アセットと一緒にリポジトリに存在しているわけではありません。

この場合、画像管理に複数のプロセスが必要になります。たとえば、サイトの構築と管理に使用される画像アセット(背景、アイコン、ロゴなど)の開発レベルのタスクと、サイトの使用によって生成された画像アセット(編集チームが投稿に埋め込まれた写真やユーザーがアップロードしたアバターなど)に関連する画像アセットに関する作業です。コンテキストは異なるかもしれませんが、最終的な目標は同じです。開発チームが定義した設定に基づいてエンコードと圧縮を自動的に行うことです。

幸い、ローカル開発ワークフローで学んだ画像処理ライブラリは、さまざまなコンテキストで活用できます。レスポンシブ画像マークアップに画一的なアプローチはありませんが、これらのシステムには、適切なデフォルト、構成オプション、API フックが用意されており、簡単に実装できます。

静的サイト生成ツール

タスクランナーとは異なり、Jekyll や Eleventy のような静的サイト生成ツールは画像に類似しています。これらのツールを使用してデプロイ可能なウェブサイトを作成するには、CSS の圧縮や、JavaScript のトランスパイルとバンドルなどのアセットの管理が必要です。ご想像のとおり、これらのツールを使用すると、すでに学習したライブラリの多くを使用して、画像アセットを同じ方法で処理できます。

公式の Eleventy 用画像プラグインでは、Sharp を使用して、ここで学習したタスクの一部と同様に、サイズ変更、複数のソースサイズの生成、再エンコード、圧縮を行います。

タスクランナーとは異なり、静的サイト生成ツールは、それらのライブラリの構成と使用方法、および本番環境サイト用に生成されるマークアップの両方を直接把握します。つまり、レスポンシブ画像マークアップの自動化に多くのことを行うことができます。たとえば、画像を表示するためのショートコードの一部として呼び出された場合、このプラグインは Sharp に渡される設定オプションに従って HTML を出力します。


const Image = require("@11ty/eleventy-img");
module.exports = function(eleventyConfig) {

async function imageShortcode(src, alt, sizes="100vw") {
  let metadata = await Image(src, {
  formats: ["avif", "webp", "jpeg"],
  widths: [1000, 800, 400],
  outputDir: "_dist/img/",
  filenameFormat: function( id, src, width, format, options ) {
      const ext = path.extname( src ),
        name = path.basename( src, ext );

      return `${name}-${width}.${format}`
  }
  });

  let imageAttributes = {
  alt,
  sizes,
  loading: "lazy"
  };

  return Image.generateHTML(metadata, imageAttributes);
}

eleventyConfig.addAsyncShortcode("respimg", imageShortcode);
};

次のように、デフォルトの画像構文の代わりにこのショートコードを使用できます。

{‌% respimg "img/butterfly.jpg", "Alt attribute.", "(min-width: 30em) 800px, 80vw" %}

上記のように複数のエンコードを出力するように構成されている場合、生成されるマークアップは、対応する <source> 要素、type 属性、srcset 属性を含む <picture> 要素となり、生成された候補サイズのリストがあらかじめ完全に入力されています。

<picture><source type="image/avif" srcset="/img/butterfly-400.avif 400w, /img/butterfly-800.avif 800w, /img/butterfly-1000.avif 1000w" sizes="(min-width: 30em) 800px, 80vw"><source type="image/webp" srcset="/img/butterfly-400.webp 400w, /img/butterfly-800.webp 800w, /img/butterfly-1000.webp 1000w" sizes="(min-width: 30em) 800px, 80vw"><source type="image/jpeg" srcset="/img/butterfly-400.jpeg 400w, /img/butterfly-800.jpeg 800w, /img/butterfly-1000.jpeg 1000w" sizes="(min-width: 30em) 800px, 80vw"><img alt="Alt attribute." loading="lazy" src="/img/butterfly-400.jpeg" width="1000" height="846"></picture>

もちろん、このプラグインは、レンダリングされたレイアウト内の画像の最終的なサイズと位置を知ることができないため、実行可能な sizes 属性をgenerateすることはできません。ただし、マークアップを生成する際に、入力として受け付けます。これは RespImageLint のもう一つの役割です。

フレームワーク

クライアントサイドのレンダリング フレームワークでは、画像アセット自体を編集、エンコード、圧縮するために、タスクランナーまたは Webpack などのバンドラが必要になります。たとえば、レスポンシブ ローダーも、Sharp ライブラリを使用して画像アセットを再保存しています。その後、画像をオブジェクトとして import できます。

  import imageAVIF from 'img/butterfly.jpg?sizes[]=400,sizes[]=800,sizes[]=1000&format=avif';
  import imageWebP from 'img/butterfly.jpg?sizes[]=400,sizes[]=800,sizes[]=1000&format=webp';
  import imageDefault from 'img/butterfly.jpg?sizes[]=400,sizes[]=800,sizes[]=1000';

インポートした画像は、React の Image コンポーネントなどの抽象化によって使用したり、レスポンシブ画像のマークアップに直接入力したりできます。

<picture>
  <source type='image/avif' srcSet={imageAVIF.srcSet} sizes='…' />
  <source type='image/webp' srcSet={imageWebp.srcSet} sizes='…' />
  <img
    src={imageDefault.src}
    srcSet={imageDefault.srcSet}
    width={imageDefault.width}
    height={imageDefault.height}
    sizes='…'
    loading="lazy"
  />

クライアント側でレンダリングを行うフレームワークは、Lazysizessizes="auto" の有力な候補です。これにより、ほぼ完全に自動化されたレスポンシブ画像を実現できます。

コンテンツ管理システム

WordPress は、ネイティブ レスポンシブ画像マークアップをいち早く取り入れた API です。WordPress 4.4 で導入されて以来、この API は段階的に改良され、WebP のサポートと出力 MIME タイプの制御が追加されています。WordPress コアは、ImageMagick PHP 拡張機能(または GD ライブラリがないもの)を利用するように設計されています。

WordPress 管理インターフェースから画像をアップロードすると、ローカルマシンの場合とほぼ同じ方法で、そのソースイメージを使用してユーザー向けのファイルがサーバーで生成されます。デフォルトでは、WordPress から出力される画像には、テーマで構成された画像サイズに基づいて srcset 属性が生成されます。

生成された画像について構成できる主な設定は、圧縮品質出力 MIME タイプの 2 つです。

たとえば、生成されるすべての画像のデフォルトの圧縮品質を 70 に設定するには、次のように記述します。

add_filter( 'wp_editor_set_quality', function() { return 70; } );

さらに圧縮率を上げるには、次のようにして、アップロードした JPEG 画像の出力形式を WebP に切り替えます。

add_filter( 'image_editor_output_format', function( $mappings ) {
  $mappings[ 'image/jpeg' ] = 'image/webp';
    return $mappings;
} );

WordPress はアップロードされた画像から生成されるすべての代替カットとエンコードを完全に理解しているため、wp_get_attachment_image_srcset() などのヘルパー関数を使用して、生成された添付画像の完全な srcset 値を取得できます。

ここまでおわかりになったと思いますが、sizes 属性を使ったものはややわかりにくくなっています。レイアウトでの画像の使用方法に関する情報がない場合、WordPress は現在、「この画像は利用可能なビューポートの 100% を、最大のソースの固有のサイズまで占有するべきである」という実質的な sizes 値に設定されています。これは予測可能なデフォルトですが、実際のアプリケーションに適したものではありません。wp_calculate_image_sizes() を使用して、コンテキストに応じた sizes 属性をテンプレートに設定してください。

もちろん、開発チームとユーザーの双方にとって最新のイメージ ワークフローを高速化することに特化した、数え切れないほどの WordPress プラグインがあります。特に素晴らしいのは、Jetpack の Site Accelerator(旧「Photon」)などのプラグインを使用すると、サーバーサイドでエンコードのネゴシエーションを行い、ブラウザがサポートできる最小かつ効率的なエンコードをユーザーが受け取れるようになります。<picture>type のマークアップ パターンは必要ありません。コンテンツ配信ネットワークは、CMS から独立して独自に活用できる画像コンテンツ配信ネットワークを利用して行います。

これは Shopify のようなホスト型 CMS ソリューションにも当てはまりますが、メカニズム自体は若干異なります。代替画像ソースと対応する srcset 属性の生成<picture> 要素によるアート ディレクションに対して同様のフックを提供します。