viteでのアセット最適化2025
2025.11.28 09:00
2025.11.28 09:56
静的サイトやWordPressテーマの開発で、画像の最適化は必須の作業です。しかし、手動で画像を圧縮するのは手間がかかりますし、ディレクトリ構造が複雑になると管理も大変になります。
今回は、Viteのビルドプロセスに組み込んで、画像を階層構造を保ったまま自動で最適化する方法を紹介します。
目次
やりたいこと
- ビルド時に画像を一括で最適化したい
- 元の画像形式(JPEG/PNG/WebP/GIF/SVG)を保持したい
- ディレクトリの階層構造を維持したい
assets/img_src/→assets/img/のように、プロジェクト内で完結させたい
必要なパッケージのインストール
まず、画像処理に必要なパッケージをインストールします。
npm install -D sharp glob- sharp: 高速な画像処理ライブラリ
- glob: ファイルパターンマッチング用
Viteの設定
vite.config.js にカスタムプラグインを作成します。
import { defineConfig } from 'vite'
import path from 'path'
import fs from 'fs/promises'
import sharp from 'sharp'
import { glob } from 'glob'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const imageOptimizePlugin = () => {
return {
name: 'vite-image-optimize',
async closeBundle() {
console.log('\n📸 画像を最適化中...\n')
// assets/img_src 配下の全画像を取得
const images = await glob('assets/img_src/**/*.{jpg,jpeg,png,gif,webp,svg}', {
nodir: true
})
console.log(`見つかった画像: ${images.length}件\n`)
for (const imgPath of images) {
try {
// 相対パスを取得
const relativePath = path.relative('assets/img_src', imgPath)
// 出力先のパス
const outputPath = path.join('assets/img', relativePath)
const ext = path.extname(imgPath).toLowerCase()
// 出力先ディレクトリを作成
await fs.mkdir(path.dirname(outputPath), { recursive: true })
// SVGはそのままコピー
if (ext === '.svg') {
await fs.copyFile(imgPath, outputPath)
console.log(`✓ コピー: ${relativePath}`)
continue
}
// sharpで最適化
let pipeline = sharp(imgPath)
switch (ext) {
case '.jpg':
case '.jpeg':
pipeline = pipeline.jpeg({
quality: 85,
progressive: true
})
break
case '.png':
pipeline = pipeline.png({
quality: 85,
compressionLevel: 9
})
break
case '.webp':
pipeline = pipeline.webp({
quality: 85
})
break
case '.gif':
pipeline = pipeline.gif()
break
}
await pipeline.toFile(outputPath)
console.log(`✓ 最適化: ${relativePath}`)
} catch (error) {
console.error(`✗ エラー: ${imgPath}`, error.message)
}
}
console.log('\n✨ 画像の最適化が完了しました\n')
}
}
}
export default defineConfig({
plugins: [
imageOptimizePlugin()
],
build: {
outDir: 'dist',
rollupOptions: {
input: path.resolve(__dirname, 'assets/js/src/main.js'),
output: {
entryFileNames: 'js/[name].js',
chunkFileNames: 'js/[name].js',
assetFileNames: (assetInfo) => {
if (assetInfo.name.endsWith('.css')) {
return 'css/[name][extname]'
}
return 'assets/[name][extname]'
}
}
}
}
})ディレクトリ構造
このプラグインを使うと、以下のように階層構造を保ったまま画像が最適化されます。
入力(最適化前)
assets/
└── img_src/
├── base/
│ ├── hero.jpg
│ └── logo.png
├── pages/
│ ├── about.jpg
│ └── contact.jpg
└── icon/
└── favicon.svg出力(最適化後)
assets/
└── img/
├── base/
│ ├── hero.jpg ← 最適化済み
│ └── logo.png ← 最適化済み
├── pages/
│ ├── about.jpg ← 最適化済み
│ └── contact.jpg ← 最適化済み
└── icon/
└── favicon.svg ← そのままコピービルドの実行
npm run build実行すると、以下のようなログが表示されます:
📸 画像を最適化中...
見つかった画像: 15件
✓ 最適化: base/hero.jpg
✓ 最適化: base/logo.png
✓ 最適化: pages/about.jpg
✓ 最適化: pages/contact.jpg
✓ コピー: icon/favicon.svg
✨ 画像の最適化が完了しましたカスタマイズ
画質の調整
ファイルサイズと画質のバランスを調整したい場合は、quality の値を変更します:
// より高品質(ファイルサイズ大)
quality: 90
// よりファイルサイズ重視
quality: 75入力・出力パスの変更
プロジェクトの構成に合わせてパスを変更できます:
// 入力
const images = await glob('img_src/**/*.{jpg,jpeg,png,gif,webp,svg}', {
nodir: true
})
// 出力
const outputPath = path.join('dist/img', relativePath)補足:PostCSSの設定
CSS内で画像を参照する場合は、postcss.config.js も設定しておくと便利です:
export default {
plugins: {
autoprefixer: {},
...(process.env.NODE_ENV === 'production' ? {
cssnano: {
preset: ['default', {
discardComments: {
removeAll: true,
},
}]
}
} : {})
}
}npm install -D autoprefixer cssnano postcssこの処理の呼び方
この作業は以下のような用語で呼ばれます:
- アセット最適化 (Asset Optimization) – 画像、CSS、JSなどのリソースを最適化すること
- 画像最適化 / 画像圧縮 (Image Optimization / Image Compression) – 今回の具体的な処理内容
- ビルドプロセス / ビルドパイプライン (Build Process / Build Pipeline) – ビルド時に実行される一連の処理
- ビルドプラグイン (Build Plugin) – Viteのカスタム機能
まとめ
Viteのカスタムプラグインを使うことで、以下のことが実現できました:
- ビルド時に画像を自動で最適化
- 元の画像形式を保持
- ディレクトリの階層構造を維持
- プロジェクト内で完結する設定
この方法を使うことで、手動での画像圧縮作業から解放され、
開発に集中できるようになりました。
今回は以上です!