NewBeginnings
Web制作

TinyPNGが高いので、画像圧縮ツールをsharpで自作してnpmに公開した(gulpでもgulpなしでも使える)

8分で読めます
この記事の要点

画像圧縮の定番TinyPNGは商用・枚数で有料になるため、sharp(libvips)ベースの画像圧縮ツール gulp-sharp-compress を自作してnpm/GitHubにMITで公開した。JPEGはmozjpeg、PNGは減色、WebP/AVIFにも対応。gulpプラグインとして使えるほか、compressBuffer()でgulpなしでもNodeスクリプトやサーバーレスで使える。導入は npm install gulp-sharp-compress。

結論から言うと、画像圧縮の定番「TinyPNG」を商用で使い続けるのがもったいなくなったので、同じようなことを sharp でローカル完結できる画像圧縮ツールを自作して、npm と GitHub に MIT ライセンスで公開しました。

パッケージ名は gulp-sharp-compress です(ソースは GitHub にあります)。名前のとおり gulp プラグインですが、v1.1.0 からは gulp なしでも使えるようにしてあります。

この記事では、なぜ作ったか・インストール方法・中で何をやっているか(仕組み)・gulp での使い方・gulp を使わない使い方、をまとめます。

なぜ作ったか(TinyPNG課金問題)

TinyPNG / TinyJPG は mozjpeg などを使った、とてもよくできた画像圧縮サービスです。普段使いには文句なしですが、無料で使える枠は月およそ500枚で、それを超える商用利用はAPIの従量課金か有料プランが必要になります。受託でサイトを量産していると、この枚数はすぐに超えます。

そして、やっていることの中心は「JPEGはmozjpeg、PNGは減色(パレット量子化)で軽くする」です。これは sharp(内部は libvips)を使えば、自分のマシンの中だけで完結できます。だったら自前でやってしまえば、枚数は無制限・追加料金ゼロ・画像を外部にアップロードする必要もない。そう考えて作りました。

インストール

npm install gulp-sharp-compress

必要なのは Node.js 18 以上です。圧縮エンジンの sharp は npm install 時にプラットフォーム用のバイナリが入るので、別途のネイティブビルドはいりません。gulp は peerDependencies(任意)なので、後述の compressBuffer だけ使うなら gulp 自体は無くても動きます。

中で何をやっているか(仕組み)

圧縮の本体は sharp です。フォーマットごとに、定番のエンコーダを使い分けています。

  • JPEG → mozjpeg(TinyPNG/Squoosh と同系統)
  • PNG → パレット量子化(pngquant 相当の減色)
  • WebP → libwebp
  • AVIF → libaom

単にエンコードするだけでなく、Web制作で実際にハマりがちな処理もパイプラインに入れてあります。

  • 向きの自動補正: EXIF の回転情報を先に画素へ焼き込んでからエンコードします。これをやらないと、メタデータを剥がした瞬間に縦写真が横倒しになります(自分が実際に踏んだ事故です)。
  • メタデータ除去: EXIF/GPS などを既定で削ります(色が重要な画像向けに ICC プロファイルだけ残すオプションもあります)。
  • 任意のリサイズ: maxWidth / maxHeight で上限を指定できます(拡大はしません)。
  • 賢くスキップ: 同じフォーマットで再エンコードして逆に大きくなった場合は、元の画像をそのまま返します(戻り値の skipped が true になります)。
  • アニメGIF / WebP は全フレームを保持します(先頭1枚に潰しません)。

つまり「TinyPNGの代わり」というより、受託のWeb制作で毎回やっている画像まわりの処理を一通り入れた道具、というのが実態に近いです。

gulp での使い方

gulp-imagemin の差し替え(drop-in replacement)として使えます。

import gulp from 'gulp';
import compress, { webp, avif } from 'gulp-sharp-compress';

// そのままのフォーマットで圧縮
gulp.src('src/images/**/*.{jpg,png}', { encoding: false })
  .pipe(compress({ quality: 80 }))
  .pipe(gulp.dest('dist/images'));

// WebP に変換して出力
gulp.src('src/images/**/*.{jpg,png}', { encoding: false })
  .pipe(webp({ quality: 80 }))
  .pipe(gulp.dest('dist/images'));

1点だけ注意で、Gulp 5 はバイナリファイルに { encoding: false } が必要です(つけ忘れると画像が壊れます)。webp / avif のほかに jpeg / png のヘルパーもあり、format オプションで明示的に変換先を指定することもできます。

gulp がなくても使える(compressBuffer)

gulp 前提のプラグインだと、Next.js のスクリプトやサーバーレス関数の中では使いにくいです。そこで v1.1.0 で、Buffer を1枚渡すと圧縮済みの Buffer を返す compressBuffer(input, options) を足しました。これは gulp 非依存で、素の Node スクリプトでも他のビルドツールでも動きます。

import { readFile, writeFile } from 'node:fs/promises';
import { compressBuffer } from 'gulp-sharp-compress';

const input = await readFile('photo.png');

// AVIF に変換
const { data, originalSize, compressedSize } = await compressBuffer(input, {
  format: 'avif',
  quality: 60,
});
await writeFile('photo.avif', data);

console.log(originalSize, '→', compressedSize);

戻り値は { data, format, originalSize, compressedSize, skipped } です。向きの補正・メタデータ処理・リサイズ・バリデーションは gulp パイプラインとまったく同じ挙動になります。ちなみに、このコーポレートサイトのブログのアイキャッチも、この compressBuffer で webp 化しています。

実際どれくらい軽くなるか

手元で1枚(PNG・約1.3MB)を compressBuffer に通してみた結果です。

  • PNG 圧縮(同フォーマット): 約1.3MB → 約334KB(-74%)
  • WebP 変換: 約35KB(-97%)
  • AVIF 変換: 約18KB(-99%)

削減率は元画像によって変わりますが、WebP / AVIF まで使うと、写真でもかなり小さくできます。

ライセンスとリンク

MIT ライセンスなので、商用利用・改変・再配布すべて自由です。npm / GitHub に置いてあります。

受託でサイトを作るなら画像最適化は避けて通れません。外部サービスに毎月払う代わりに、ローカルで完結する道具を1つ持っておくと地味に楽になります。よければ使ってみてください。バグや要望は GitHub の Issue へどうぞ。

よくある質問

gulp-imagemin とどう違いますか?
圧縮エンジンが sharp(内部は libvips)ベースで高速です。JPEGはmozjpeg、PNGはパレット量子化(減色)、さらにWebP/AVIFへの変換にも対応します。gulp-imagemin の差し替え(drop-in replacement)として使えます。
gulpがなくても使えますか?
使えます。compressBuffer(input, options) という関数があり、画像のBufferを渡すと圧縮済みのBufferを返します。gulp非依存なので、素のNodeスクリプト・サーバーレス関数・他のビルドツールでも動きます。
TinyPNGと品質は変わりますか?
JPEGはmozjpeg、PNGはパレット量子化(pngquant相当)と、TinyPNGと近い系統のエンコーダを使っています。加えてWebP/AVIFへの変換もできます。削減率は元画像によって変わります。
商用利用できますか?
できます。MITライセンスで公開しているので、商用利用・改変・再配布が無料で可能です。

大分でホームページ制作・リニューアルをお考えなら、株式会社NewBeginningsにご相談ください。見た目だけでなく、問い合わせが増える設計・公開後の更新運用まで考えたWeb制作を、大分の中小企業向けに提供しています。WordPress・Next.js対応のプラン内容や制作事例は 大分のホームページ制作サービス のページで詳しくご紹介しています。目的と予算に合わせた最適な構成をご提案しますので、素材やイメージが揃っていない段階でもご相談いただけます。

初回30分の無料相談はこちら
芦刈庸介のプロフィール画像
この記事の担当芦刈庸介代表取締役 / エンジニア

大分県出身。フリーランスを経て2026年に株式会社NewBeginningsを設立。Web制作・アプリ開発・DX支援を通じて、地域の中小企業のデジタル化を伴走支援しています。「ITやDXは難しい」を「IT・DX・AIで楽になった」に変えることがミッション。

シェアする

次に読むおすすめページ

他のサービスもご覧ください

関連記事

自社プロダクト

NewBeginnings が開発・運営する SaaS

CONTACT

まずは、気軽にご相談ください。

初回30分の無料ヒアリング / 難しい用語なしでご説明