4 ポイント 投稿者 GN⁺ 2024-03-26 | 1件のコメント | WhatsAppで共有
  • JampackはStatic Site Generatorの出力を受け取り、ユーザー体験とCore Web Vitalsスコアを最適化する後処理ツールであり、バンドラーやフレームワークではない
  • HTMLの<img><picture>をレスポンシブ画像に変換し、WebP・AVIFなどの形式、srcsetsizeswidthheightloading="lazy"decoding="async"などを自動で追加する
  • CDN画像はURLパラメータベースのsrcsetでレスポンシブ対応でき、外部画像は_jampack配下にダウンロードして最適化済みのローカル画像に置き換えられる
  • Above-the-foldのアセットは高い優先度で処理し、小さな画像はHTMLにインライン化し、below-the-foldの画像とiframeは遅延読み込みする
  • 静的サイトのビルド結果フォルダに対してnpx @divriots/jampack./distを実行する形で適用し、CSS・JS・HTML・SVG・画像の圧縮まで2回目のパスで実行する

Jampackの役割

  • JampackはStatic Site Generator、つまりSSGが生成した出力を入力として受け取り、静的Webサイトを最適化する
  • 目的はユーザー体験とCore Web Vitalsスコアを改善すること
  • READMEではJampackを「バンドラーでもフレームワークでもない」と区別している
  • 紹介記事はRead the introduction blog postで提供されている

画像最適化

  • 通常の<img>はレスポンシブ画像に変換される
    • 元のsrcに対してWebPファイルを作成し、srcsetを追加する
    • sizes="100vw"loading="lazy"decoding="async"widthheightなどの属性が追加される
  • <picture>要素は複数の画像形式を含むレスポンシブ構造に変わる
    • AVIF用の<source type="image/avif">が追加される
    • WebP用の<source type="image/webp">が追加される
    • 元の<img>にもsrcsetsizesloadingdecodingwidthheightが入る
  • 画像最適化機能はoptimize-imagesドキュメントにつながるが、README内の該当リンクは相対パスになっている

CDNおよび外部画像の処理

  • CDN画像はリモートURLを維持しながらレスポンシブなsrcsetを追加できる
    • 例ではUnsplashの画像URLにwfit=minauto=formatパラメータを付け、複数幅の候補を作成する
    • 元の画像にもloading="lazy"decoding="async"sizes="100vw"が追加される
  • 外部画像はダウンロード後、最適化済みのローカルファイルに置き換えられる
    • 例では外部のUnsplash画像を_jampack/ab99b9d280ce4cf7cfc810b59f3a7739.jpg.webpのようなパスに変換する
    • 変換後の画像にはwidthheightsrcsetsizesloadingdecodingが含まれる

Above-the-foldとCSS・リンク最適化

  • Jampackはabove-the-foldアセットを個別に最適化する
    • 画像はより高い優先度で読み込まれる
    • 小さな画像はHTMLに埋め込まれる
  • below-the-foldアセットは遅延読み込みされる
    • 画像とiframeがlazy loadの対象となる
  • Critical CSSはHTMLにインライン化される
    • 目的はスタイルシートのダウンロードと解析中に発生しうるFOUCを避けること
    • 残りのCSSは遅延読み込みされる
  • リンクのプリフェッチは、今後のページ遷移を高速化するための機能
    • quicklinkを使い、リンクがviewportに入ったときに動的に処理できる

アセット圧縮と実行方法

  • Jampackは2回目のパスで、手を加えていないすべてのアセットを圧縮し、同じ名前と同じ形式を維持する
  • 拡張子別の圧縮ツールは以下のとおり
  • 静的Webサイトがdistフォルダにある場合、次のコマンドで実行する
npx @divriots/jampack ./dist
  • 追加オプションはCLI optionsで確認できる

ユースケースと名前の意味

1件のコメント

 
GN⁺ 2024-03-26
Hacker Newsのコメント
  • まさに探していたツール。こういう画像最適化のためにSharpベースのスクリプトを自作して使っていたが、Jampackがそれを完全に置き換えてくれて、しかもずっとよく動く
    Quartoの静的サイトをビルドしたあとにJampackを走らせたところ、フォルダサイズが32%減少し、今のところ目立った欠点はない
    PageSpeed Insightsでは、Jampack適用前はモバイルがパフォーマンス52、アクセシビリティ73、ベストプラクティス100、SEO 85、デスクトップはパフォーマンス90、アクセシビリティ75、ベストプラクティス100、SEO 82だった
    適用後はモバイルがパフォーマンス49、アクセシビリティ80、ベストプラクティス100、SEO 92、デスクトップはパフォーマンス85、アクセシビリティ82、ベストプラクティス100、SEO 91になった

    • LighthouseやPageSpeed Insightsのスコアはぶれやすい。こうした性能比較をするときは、複数回実行して中央値を見るほうがよい
      「Lighthouseスコアを5回実行した中央値は、1回実行より2倍安定する」という資料もある: https://developers.google.com/web/tools/lighthouse/variabili...
    • 気に入ってもらえてうれしい。ただ、パフォーマンス指標はもっと良くなると思っていた。差し支えなければ、Jampack適用前の静的サイトの出力を共有してもらえれば見てみたい
      georges [at] divriots [dot] com
  • ApacheとNginx向けのPageSpeedモジュールを思い出す: https://developers.google.com/speed/pagespeed/module

    • そのプロジェクトはもうメンテナンスされていないと理解している
      GitHubリポジトリもアーカイブされている: https://github.com/apache/incubator-pagespeed-ngx
      どこか別の場所へ移ったのだろうか?
  • これはかなり気に入った。使ってみるつもり
    いまいちだと感じた人がいるなら、欠点を指摘してほしい。自分には、Cを超高度に最適化されたアセンブリにコンパイルするのに近く、しかも自分ではやりたくない作業を確実に代わりにやってくれるツールに見える

    • HTMLとCSSに超高度に最適化されたアセンブリのようなものを配布しなければならないなら、私たちが正しい方向に進んでいるのか分からない
      できるだけ単純で直感的なHTMLとCSSを書けば、あらゆるデバイスのブラウザがそのまま問題なくレンダリングできるべきだと思う
      本当にそのレベルの最適化成果物を配布しなければならないなら、HTMLとCSSは完全に飛ばして、高度に最適化されたWebAssemblyを配布し、開発者には好きな言語を使わせたほうがよい
  • SSG出力のUnicode範囲に基づいてフォントをサブセット化し、CSSで定義されたfont-feature-settingsをもとにOpenType軸を固定する方法があるとよい

    • その通りで、フォント周りにはできる面白いことがたくさんある。TODOには、正しいメトリクスを持つシステムフォント代替を自動追加してCLSを自動改善する作業がある
      それが言っている「font-feature-settingsベースのOpenType軸固定」のことなのか、それとも別の意味なのか気になる
      フォントのサブセット最適化もやりたいが、どれほど改善するのかはまだよく分からない。手動で試したことがあるのか気になる
    • ブラウザ/システムフォントを使えばフォントサイズ0に最適化できるのに、わざわざやる必要があるのだろうか
  • 別スタイルシートに置かずインライン化すべき重要CSSを特定するという発想は興味深い
    重要CSSと非重要CSSを原理的に区別する方法があるのかと期待した。たとえば :hover のようなユーザー操作の効果は常に非重要とみなす、など
    しかし使っているライブラリは、ページをレンダリングしてどのルールが重要かを最善推定する方式なので、少し残念: https://github.com/GoogleChromeLabs/critters

    • CSSが50KB未満なら、そのままインライン化すればよい。50KBを超えるCSSがあるなら、たぶん何かを間違えている
      もちろんフォントまでインライン化するなら話は分かるが、それ以外のスタイルだけで50KBを超えるなら、たいていは方向性を誤っている
      真面目な話、インライン化はウォームキャッシュと比べても性能面で非常に有利で、外部スタイルシートやスクリプトのほうが良くなる閾値は思ったより高く、一般的な市場基準では数百KBに達することもある
      重要CSSという概念は、根本問題を直すのではなく、無駄にした性能を少し取り戻そうとする敗北主義的アプローチのように感じる
      ただし、これは体系的な手法ではなく、軽い経験と観察に基づく判断だ。誰かがこの概念をもっときちんと測定してくれるとよいが、自分がやることはなさそうだ
  • これは、そもそも人々がSSGとプラグインを選ぶさまざまな用途をカバーしているように見える。特にAstroやEleventyを選ぶ場合はなおさらだ
    別個のビルド後ステップにしておくことを好む理由はあるだろうか? 開発中の再ビルドは速くなるが、画像のwidth指定のようなものを追加することで生じる微妙なバグを見逃す可能性とのトレードオフに見える

  • Webページのレイアウト作業が嫌いで、学ぶ気もないが、ときどきやらなければならない立場としては、このツールはとても良さそう

  • 良さそう。ただ、個人的にはページをファーストビューの下へスクロールしたときに画像を待たされるのが嫌い
    デフォルトの動作では、ファーストビューのコンテンツが終わったあと、残りの下側コンテンツをバックグラウンドで読み込むのだろうか?

    • そうではない。ブラウザのネイティブ遅延読み込みを利用している。主要ブラウザは loading="lazy" 属性を「この画像/iframeがほぼ見えるようになるまで読み込まない」という意味として扱う: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/im...
      ただしアスペクト比はインラインで入れるので、読み込み後にレイアウトが変わることはない。遅延読み込みの最大の罪を避けているわけだ
    • @lelandfe が指摘したように、Jampackはブラウザネイティブの loading="lazy" を使っている
      現時点ではこの動作を変える方法はないが、ページ全体の読み込み後にファーストビュー下の画像をバックグラウンドで先読みするオプションを追加することはできる。かなり良いアイデアだ
      ただ、ページ下部の不要な画像まで読み込んでしまうのではないかと心配している。オプションなら各自でオン・オフできるので問題なさそうだ
  • 本番環境で使える静的サイトジェネレータにはどんなものがある? このツールで出力結果をさらに最適化できそうだ
    たとえば昨日は、DivjoyのReactウェブサイトを単純なHTMLに変換してS3バケットから配信しようと、サンプルに従って丸一日費やした。こんなに難しいとは思わなかったし、まだ苦戦している
    理想を言えば、S3バケットに自動デプロイしてドメインまで接続してくれる何かがあるとよい。有料なのに開発者はいなくなり、Discordも放置されているのがつらい。だから自分はいつもFOSSのほうを好む

    • Hugo、Zola、Jekyllあたりがある
      ある程度はこうした機能の一部を備えている
  • 自分のプロジェクトの一つでは大きな変化はなかった。たとえば全体のバンドルサイズは減ったが、gzipサイズは増えたので、実際には自分にとって純損だった
    それでもCSS改善は実際に役立ったように思う
    アイデア自体は素晴らしく、プロジェクトに画像があればたぶん役に立っただろう

    • 画像がなければ利点が限られるのはその通り。また、ブラウザ互換性を自動改善するため、最終的なCSSサイズが大きくなることもある
      browserlistを空文字列に設定すればこの機能は無効化できる: https://jampack.divriots.com/features/browser-compatibility/