qrac / minista

Static site generator with 100% static export from React and Vite.
https://minista.qranoko.jp
165 stars 13 forks source link

画像最適化コンポーネントを実装 #98

Closed qrac closed 1 year ago

qrac commented 1 year ago

v3ではViteプラグインでも代用できたが、Viteプラグイン開発者が今後もViteのアップデートに追従していくという保証はない。ビルトインコンポーネント(例えば <Image /> <Picture >)で画像を最適化できた方が未来への不安を抱えずに済むし開発体験も良いはずなので作る。

参考:画像タグ

参考:画像コンポーネント

参考:画像処理

qrac commented 1 year ago

自動的にwidthとheightを設定できると楽。useAutoSize propsを作っておくとか。

qrac commented 1 year ago

背景画像はobject-fitが出てから案件でほとんど使っていないので作らない予定。

qrac commented 1 year ago

ざっくり仕様

qrac commented 1 year ago

開発中は基本的に元画像を参照するが、アスペクト比が本番で変わるものは確認できないとまずいので最高解像度の一時ファイルを生成して当てる。ページ内の数枚、キャッシュ生成を行えばパフォーマンスに問題はなさそう。

import { Image, Picture } from "minista"

export default function () {
  return (
    <>
      <div>
        <Image src="/src/assets/image.png" width={800} />
      </div>
      <div>
        <Image
          src="/src/assets/image.png"
          width={200}
          layout="fixed"
          aspect={"1:1"}
        />
      </div>
      <div>
        <Picture src="/src/assets/image.png" formats={["webp", "inherit"]} />
      </div>
    </>
  )
}
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
  </head>
  <body>
    <div>
      <img src="/src/assets/image.png" sizes="(min-width: 2208px) 2208px, 100vw" width="800" height="392" alt="" decoding="async" loading="lazy">
    </div>
    <div>
      <img src="/node_modules/.minista/images/serve/image-1080x1080.png" sizes="(min-width: 200px) 200px, 100vw" width="200" height="200" alt="" decoding="async" loading="lazy">
    </div>
    <div>
      <picture>
        <source srcset="/src/assets/image.png" sizes="(min-width: 2208px) 2208px, 100vw" width="2208" height="1080">
        <img src="/src/assets/image.png" sizes="(min-width: 2208px) 2208px, 100vw" width="2208" height="1080" alt="" decoding="async" loading="lazy">
      </picture>
    </div>
  </body>
</html>
qrac commented 1 year ago

本番ビルド

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
  </head>
  <body>
    <div>
      <img srcset="/assets/images/image-320x157.png 320w, /assets/images/image-400x196.png 400w, /assets/images/image-640x314.png 640w, /assets/images/image-800x392.png 800w, /assets/images/image-1024x502.png 1024w, /assets/images/image-1280x627.png 1280w, /assets/images/image-1440x706.png 1440w, /assets/images/image-1920x941.png 1920w, /assets/images/image-2208x1080.png 2208w" src="/assets/images/image-2208x1080.png" sizes="(min-width: 2208px) 2208px, 100vw" width="800" height="392" alt="" decoding="async" loading="lazy">
    </div>
    <div>
      <img srcset="/assets/images/image-200x200.png 1x, /assets/images/image-400x400.png 2x" src="/assets/images/image-200x200.png" sizes="(min-width: 200px) 200px, 100vw" width="200" height="200" alt="" decoding="async" loading="lazy">
    </div>
    <div>
      <picture>
        <source srcset="/assets/images/image-320x157.webp 320w, /assets/images/image-400x196.webp 400w, /assets/images/image-640x314.webp 640w, /assets/images/image-800x392.webp 800w, /assets/images/image-1024x502.webp 1024w, /assets/images/image-1280x627.webp 1280w, /assets/images/image-1440x706.webp 1440w, /assets/images/image-1920x941.webp 1920w, /assets/images/image-2208x1080.webp 2208w" sizes="(min-width: 2208px) 2208px, 100vw" width="2208" height="1080" type="image/webp">
        <img srcset="/assets/images/image-320x157.png 320w, /assets/images/image-400x196.png 400w, /assets/images/image-640x314.png 640w, /assets/images/image-800x392.png 800w, /assets/images/image-1024x502.png 1024w, /assets/images/image-1280x627.png 1280w, /assets/images/image-1440x706.png 1440w, /assets/images/image-1920x941.png 1920w, /assets/images/image-2208x1080.png 2208w" src="/assets/images/image-2208x1080.png" sizes="(min-width: 2208px) 2208px, 100vw" width="2208" height="1080" alt="" decoding="async" loading="lazy">
      </picture>
    </div>
  </body>
</html>
qrac commented 1 year ago

Promise.all > map asyncで回している並列処理の中では、fsや変数で画像キャッシュのチェックが行えない(すべて同時実行扱い)ので並列処理の外で一度確認する必要がある。