imageminを使用して画像を圧縮するnpmスクリプトを作成して見た

サイトを高速化、パフォーマンスの改善をおこなっていくために画像の容量を極力小さくする必要があります。
そこで imagemin
というパッケージを使用して画像圧縮するスクリプトを作って行きたいと思います。
imageminで検索するとgulpを使用した画像圧縮の記事が多く出てきたため
あえてgulpを使用せずnpmスクリプトとtypescriptを使用して作って見ました。
要件としては現状のディレクトリ構成を保持しつつ画像だけ圧縮させたかったため
処理を走らせると既存の画像が圧縮されて上書するようにしています。
環境
- yarn 1.7.0
- typescript 2.9.2
早速作ってみる
パッケージのインストール
必要なパッケージをまとめてインストールします。
今回は jpg
png
gif
svg
の圧縮を対象にしています。
terminal$ yarn add glob imagemin imagemin-cli imagemin-gifsicle imagemin-jpegtran imagemin-pngquant imagemin-svgo
実行環境として typescript
で書いたコードを ts-node
で実行します。
terminal$ yarn add -D typescript ts-node
インポート
パッケージをインポートします。
index.tsimport * as imagemin from 'imagemin';
import * as imageminJpegtran from 'imagemin-jpegtran';
import * as imageminPngquant from 'imagemin-pngquant';
import * as imageminGifsicle from 'imagemin-gifsicle';
import * as imageminSvgo from 'imagemin-svgo';
import * as glob from 'glob';
対象ファイルの一覧を配列に格納
imagemin
は再帰的にディレクトリを辿ってくれなかったため
あえて glob
で対象のファイルをリスト化しました。
index.tsconst baseDir = './files';
const imagesjpg = glob.sync(`${baseDir}/**/*.jpg`);
const imagesPng = glob.sync(`${baseDir}/**/*.png`);
const imagesGif = glob.sync(`${baseDir}/**/*.gif`);
const imagesSvg = glob.sync(`${baseDir}/**/*.svg`);
一覧化したリストから処理を実行
あとはドキュメント通りにそれぞれの処理を実行します。
今回は順番に処理を実行する形で雑に縦に書いていますが
うまくまとめちゃっていいと思います。
index.tsimagesjpg.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminJpegtran()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesPng.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminPngquant()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesGif.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminGifsicle()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesSvg.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [
imageminSvgo({
plugins: [
{ removeViewBox: false },
],
}),
],
}).then(() => {
console.log(`${files} optimized`);
});
});
package.json
に実行ようのスクリプトを記述します。
package.json"scripts": {
"start": "ts-node index.ts"
},
yarnコマンド
で処理を実行します。
terminal$ yarn start
もともと圧縮していないファイルであれば約半分(50%)近く容量が圧縮できると思います。
iniimport * as imagemin from 'imagemin';
import * as imageminJpegtran from 'imagemin-jpegtran';
import * as imageminPngquant from 'imagemin-pngquant';
import * as imageminGifsicle from 'imagemin-gifsicle';
import * as imageminSvgo from 'imagemin-svgo';
import * as glob from 'glob';
const baseDir = './files';
const imagesjpg = glob.sync(`${baseDir}/**/*.jpg`);
const imagesPng = glob.sync(`${baseDir}/**/*.png`);
const imagesGif = glob.sync(`${baseDir}/**/*.gif`);
const imagesSvg = glob.sync(`${baseDir}/**/*.svg`);
imagesjpg.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminJpegtran()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesPng.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminPngquant()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesGif.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [imageminGifsicle()],
}).then(() => {
console.log(`${files} optimized`);
});
});
imagesSvg.forEach((files: string): void => {
const dir = files.split('/');
dir.pop();
imagemin([files], dir.join('/'), {
use: [
imageminSvgo({
plugins: [
{ removeViewBox: false },
],
}),
],
}).then(() => {
console.log(`${files} optimized`);
});
});
参考
imagemin-jpegtran
https://www.npmjs.com/package/imagemin-jpegtran
imagemin-pngquant
https://www.npmjs.com/package/imagemin-pngquant
imagemin-gifsicle
https://www.npmjs.com/package/imagemin-gifsicle
imagemin-svgo
https://www.npmjs.com/package/imagemin-svgo
- article
npmの事故伝播ワーム「Shai-Hulud」徹底解説:被害範囲・仕組み・今すぐ取るべき対策
- article
【完全版】Vite ライブラリモード徹底ガイド:npm 配布のための設計と落とし穴
- article
Turbopack と npm scripts の連携テクニック
- article
npm と yarn:パッケージ管理の違いとベストプラクティス
- article
【2025年3月版】JavaScript時間操作ライブラリを徹底比較!日付処理の最適解とは?
- article
【解決方法】nodenvで入れたnpmのグローバルインストールでパスが通らない場合の対処について
- article
【比較検証】Convex vs Firebase vs Supabase:リアルタイム性・整合性・学習コストの最適解
- article
【徹底比較】Preact vs React 2025:バンドル・FPS・メモリ・DX を総合評価
- article
GPT-5-Codex vs Claude Code / Cursor 徹底比較:得意領域・精度・開発速度の違いを検証
- article
Astro × Cloudflare Workers/Pages:エッジ配信で超高速なサイトを構築
- article
【2025 年版】Playwright vs Cypress vs Selenium 徹底比較:速度・安定性・学習コストの最適解
- article
Apollo を最短導入:Vite/Next.js/Remix での初期配線テンプレ集
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来