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
articlenpmの事故伝播ワーム「Shai-Hulud」徹底解説:被害範囲・仕組み・今すぐ取るべき対策
article【完全版】Vite ライブラリモード徹底ガイド:npm 配布のための設計と落とし穴
articleTurbopack と npm scripts の連携テクニック
articlenpm と yarn:パッケージ管理の違いとベストプラクティス
article【2025年3月版】JavaScript時間操作ライブラリを徹底比較!日付処理の最適解とは?
article【解決方法】nodenvで入れたnpmのグローバルインストールでパスが通らない場合の対処について
articleBun コマンド チートシート:bun install/run/x/test/build 一括早見表
articleComfyUI のインストール完全ガイド:Windows/Mac/Linux 別・最短手順
articleAnsible Push vs Pull を検証:大規模環境での配布・制御モデル
articleZustand subscribeWithSelector で発生する古い参照問題:メモ化と equalityFn の落とし穴
articleWordPress URL 設計とリライトルール:正規化と SEO を両立する作法
articleCodex プロンプト速攻リファレンス:生成/修正/要約/変換の定型文 20
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来