2026 フロント/全栈ビルド

リモート Mac・静的サイト:
Sharp / libvips / ImageMagick 意思決定マトリクス

2026.04.07 画像管線・SSG 担当向け 約 7 分で読めます

静的サイト生成(SSG)でサムネイルやレスポンシブ派生を大量に吐くと、選んだエンジン一つでメモリ曲線が変わります。本稿は Sharp(libvips バインディング)、ネイティブ libvips(CLI/他言語)、ImageMagick の三層を、フォーマット適性・並列用環境変数・一時領域・OOM リスク・CI キャッシュで横並びにし、リモート Mac 上で再現しやすいパラメータ例に落とし込みます。全体のビルド並列やヒープはSSR/フレームワークのメモリ対照と、バンドラ側のVite/Webpack キャッシュ最適化とあわせて読むと筋が通ります。

下記の package.json 断片はそのまま貼り替え可能です。

01 シナリオ:SSG で大量サムネイルを量産するとき

ブログ記事や商品カードごとに複数幅の WebP/AVIF を書き出すと、変換フェーズがビルド全体のボトルネックになります。ローカルでは成功しても、リモート Mac の共有ホストでは同時ビルドと入出力が重なり、画像ワーカーだけが限界突破することがあります。対策の軸は「同時実行の上限」「一時ファイルの置き場」「ネイティブライブラリのスレッド数」「Node ヒープ」の四つに集約できます。スタイル管線のメモリ調整はTailwind v4/PostCSS の対照表も参照し、CSS と画像のピークが重ならないようスロットをずらすと安定します。

02 Sharp・libvips・ImageMagick:三方式パラメータ対照表

以下は静的サイト向けの実務目安です。実バージョンや入力解像度で変動するため、受入れ時は同じ入力セットでピーク RSS を記録してください。

方式 主な適用フォーマット 並列・スレッド(環境変数の例) 一時ディレクトリ OOM リスクの典型 CI キャッシュのコツ
Sharp(Node) JPEG/PNG/WebP/AVIF/TIFF/GIF 入力 ほか libvips 側 VIPS_CONCURRENCY=vCPU 前後。アプリ側は同時ジョブ数を別途キューで制限 TMPDIR(大画像はディスクスプールに乗ることあり) Node ヒープ不足+無制限 Promise.all node_modules の再現性重視ならロックファイルと OS をキーに。ビルドキャッシュに .sharp 由来の再取得ログを残す
libvips(CLI/バインディング) 上記に近い。パイプライン操作が明示的 VIPS_CONCURRENCYVIPS_DISC_THRESHOLD でメモリ/ディスク切替の閾値(バイト) TMPDIR 巨大タイル読み込みや閾値未設定での同時パイプライン過多 変換コマンドと vips バージョンをキャッシュキーに含める。中間ファイルパスをワークスペース内に固定
ImageMagick 非常に広い。ポリシーでフォーマット制限推奨 MAGICK_THREAD_LIMIT。メモリ系 MAGICK_MEMORY_LIMITMAGICK_MAP_LIMITMAGICK_DISK_LIMIT(policy でも可) MAGICK_TEMPORARY_PATH または TMPDIR デフォルト上限なしに近い構成での一括変換ピーク policy.xml のハッシュをキャッシュキーに。中間生成物を artifacts で保存し二回目以降を短縮

メモ:共有 Mac では「スレッドを張り切る」より「同時プロセス本数を抑える」方が全体の予測可能性が高いことが多いです。

03 npm/pnpm スクリプトと NODE_OPTIONS の例

画像スクリプトを単独フェーズに分けると、失敗時の再実行とキャッシュ境界が明確になります。

{
  "scripts": {
    "images:thumbs": "NODE_OPTIONS='--max-old-space-size=6144' node ./scripts/generate-thumbnails.mjs",
    "build": "pnpm run images:thumbs && NODE_OPTIONS='--max-old-space-size=8192' pnpm exec vite build",
    "images:ci": "cross-env TMPDIR=$PWD/.tmp VIPS_CONCURRENCY=4 NODE_OPTIONS='--max-old-space-size=4096' node ./scripts/generate-thumbnails.mjs"
  }
}
  • npmnpm run images:thumbs 前に export NODE_OPTIONS=--max-old-space-size=6144 を CI の一ブロックにまとめると二重設定を避けられます。
  • pnpmpnpm run build 内でだけヒープを上げたい場合は、上記のようにサブスクリプト側に NODE_OPTIONS を直書きするか、pnpm exec env NODE_OPTIONS=... で局所化します。
  • ImageMagick 併用:同じジョブ内で Node と magick を起動するなら、シェルで MAGICK_THREAD_LIMIT=2 などを先に export し、CPU と磁気ディスクの競合を抑えます。

04 リモート Mac での受入れ三歩

  1. ベースライン計測:代表ブランチでフルビルドを一度走らせ、画像フェーズの wall time・最大 RSS・TMPDIR 配下のピーク使用量を記録する(他テナント負荷の低い時間帯を推奨)。
  2. パラメータ固定VIPS_CONCURRENCYMAGICK_THREAD_LIMIT/同時ジョブ数を文書化し、CI とローカルのドキュメントを一枚に揃える。
  3. キャッシュ検証:キャッシュヒット時に画像フェーズがスキップまたは増分のみになることをログで確認し、キーにロックファイル・ランタイム OS・アーキテクチャを含めて無効化漏れを防ぐ。

05 FAQ

Q. Sharp だけで十分なのに libvips CLI を併記する意味は?
Sharp は内部で libvips を利用するため、トラブルシュート時は VIPS_CONCURRENCY やディスクスプールの挙動が共通の語彙になります。バッチを Node 以外(Makefile/Go など)に分離する場合は CLI 側の知識がそのまま効きます。

Q. AVIF まで含めると遅いが、品質は落としたくない。
解像度段階を設け、最終段だけ高コストコーデックにする、または本番用とプレビュー用の二層キャッシュを分けると、PR ビルドの待ち時間を抑えられます。

Q. OOM のログが Node でなく kern で出ることがある。
ネイティブ側の確保失敗です。ヒープだけでなく ulimit、ホストの残メモリ、スワップ、同時ビルドスロットを疑ってください。

メモリとコアに余裕のあるリモート Mac で、画像パイプラインを安定再現する。

MacWww の公開ページでは、ログイン不要で料金(りょうきん)やノード仕様を比較できます。大規模 SSG やネイティブ依存のビルドを専用マシンに寄せたいチームは、トップからプランを確認し、ヘルプの接続手順に沿ってリモート Mac ビルドノードを検証してください。

リモート Mac を選ぶ(ログイン不要)