Vitus Labs
Tools Next.js Images

Tools Next.js Images

Image optimization plugin for Next.js — WebP conversion, LQIP placeholders, responsive images, SVG sprites, and compression.

@vitus-labs/tools-nextjs-images is a Next.js webpack plugin that provides image optimization via import-time resource queries. Convert to WebP, generate low-quality placeholders, create responsive variants, build SVG sprites, and compress images — all through import syntax.

Installation

npm install @vitus-labs/tools-nextjs-images

Peer dependency: next >= 14

Optional optimizer packages (install what you need):

# Compression
bun add imagemin-mozjpeg imagemin-optipng imagemin-pngquant imagemin-gifsicle imagemin-svgo

# WebP conversion
bun add webp-loader

# Responsive images
bun add responsive-loader sharp  # or jimp instead of sharp

# SVG sprites
bun add svg-sprite-loader

# Placeholders
bun add lqip-loader image-trace-loader

Quick Start

// next.config.ts
import withOptimizedImages from '@vitus-labs/tools-nextjs-images'

export default withOptimizedImages()({
  // Your standard Next.js config
})

Import Queries

Use resource queries on imports to trigger different optimizations:

// Standard optimized image
import photo from './photo.jpg'

// Convert to WebP
import webp from './photo.jpg?webp'

// Low-quality placeholder
import { src, preSrc } from './photo.jpg?lqip'

// Color palette extraction
import { palette } from './photo.jpg?lqip-colors'

// SVG trace placeholder
import trace from './photo.jpg?trace'

// Force file URL (no inlining)
import url from './photo.jpg?url'

// Force data URI inline
import inline from './photo.jpg?inline'

// Raw SVG content
import svg from './icon.svg?include'

// SVG sprite (React component)
import Icon from './icon.svg?sprite'

// Responsive variants
import responsive from './photo.jpg?size=300,600,1200'

// Skip optimization
import original from './photo.jpg?original'

Resource Query Reference

QueryPurposeOptimizedOutput
(none)Default processingYesURL or data URI
?urlForce file URLYesURL string
?inlineForce data URIYesData URI string
?includeRaw contentYesString content
?originalSkip optimizationNoURL or data URI
?webpConvert to WebPYesURL string
?lqipLow-quality placeholderNo{ src, preSrc }
?lqip-colorsPalette extractionNo{ palette }
?traceSVG trace placeholderYesURL string
?spriteSVG sprite componentVariesReact component
?size=N,N,NResponsive variantsNoResponsive image object

Configuration

import withOptimizedImages from '@vitus-labs/tools-nextjs-images'

export default withOptimizedImages({
  // Core options
  optimizeImages: true,          // Optimize in production (default: true)
  optimizeImagesInDev: false,    // Optimize in development (default: false)
  handleImages: ['jpeg', 'png', 'svg', 'webp', 'gif'],  // Formats to process
  inlineImageLimit: 8192,        // Bytes threshold for data URI inlining
  defaultImageLoader: 'img-loader',  // 'img-loader' or 'responsive-loader'

  // Output
  imagesFolder: 'images',       // Output folder name
  imagesName: '[name]-[hash].[ext]',  // Filename pattern
  removeOriginalExtension: false,     // Strip extension on format conversion

  // Optimizer options (pass-through to underlying libraries)
  mozjpeg: { quality: 80 },
  optipng: {},
  pngquant: {},
  gifsicle: { interlaced: true, optimizationLevel: 3 },
  svgo: { plugins: [{ name: 'removeViewBox', active: false }] },
  webp: { quality: 80 },
  svgSpriteLoader: { symbolId: '[name]-[hash:8]' },
  responsive: { adapter: require('responsive-loader/sharp') },
  lqip: {},
  imageTrace: {},
})({
  // Standard Next.js config
})

OptimizedImagesConfig

OptionTypeDefaultDescription
optimizeImagesbooleantrueEnable optimization in production
optimizeImagesInDevbooleanfalseEnable optimization in development
handleImagesstring[]['jpeg', 'png', 'svg', 'webp', 'gif']Image formats to process
inlineImageLimitnumber8192Bytes threshold for data URI inlining
defaultImageLoaderstring'img-loader'Default loader: 'img-loader' or 'responsive-loader'
imagesFolderstring'images'Output folder name within _next/static/
imagesNamestring'[name]-[hash].[ext]'Output filename pattern
removeOriginalExtensionbooleanfalseStrip original extension when converting
imagesPublicPathstringOverride public path
imagesOutputPathstringOverride output directory

Optimizer Options

OptionLibraryFormats
mozjpegimagemin-mozjpegJPEG
optipngimagemin-optipngPNG
pngquantimagemin-pngquantPNG (alternative)
gifsicleimagemin-gifsicleGIF
svgoimagemin-svgoSVG
webpwebp-loaderWebP conversion
svgSpriteLoadersvg-sprite-loaderSVG sprites
responsiveresponsive-loaderJPEG, PNG responsive
lqiplqip-loaderJPEG, PNG placeholders
imageTraceimage-trace-loaderJPEG, PNG, GIF traces

Format Support Matrix

FormatCompressWebP ConvertResponsiveSpriteLQIPTrace
JPEGmozjpeg?webp?size=?lqip?trace
PNGoptipng/pngquant?webp?size=?lqip?trace
SVGsvgo?sprite
GIFgifsicle?trace
WebPwebp-loaderDirect

Detected Loaders

The plugin auto-detects which optimizer packages are installed:

interface DetectedLoaders {
  jpeg: string | false      // 'imagemin-mozjpeg' or false
  png: string | false       // 'imagemin-optipng' or 'imagemin-pngquant' or false
  gif: string | false       // 'imagemin-gifsicle' or false
  svg: string | false       // 'imagemin-svgo' or false
  svgSprite: string | false // 'svg-sprite-loader' or false
  webp: string | false      // 'webp-loader' or false
  lqip: string | false      // 'lqip-loader' or false
  responsive: string | false       // responsive-loader path or false
  responsiveAdapter: string | false // 'sharp' or 'jimp' or false
}

Build Phase Behavior

PhaseOptimization
Production buildoptimizeImages setting (default: true)
Static exportoptimizeImages setting (default: true)
Development serveroptimizeImagesInDev setting (default: false)

When optimization is disabled, images are still processed (file-loader/url-loader) but no compression or conversion is applied.

SVG Sprite Components

SVG sprites generated via ?sprite become React components with metadata:

import Icon from './icon.svg?sprite'

// Render as component
<Icon />

// Access metadata
Icon.viewBox  // '0 0 24 24'
Icon.id       // 'icon-a1b2c3d4'
Icon.url      // '#icon-a1b2c3d4'

Exports

import withOptimizedImages from '@vitus-labs/tools-nextjs-images'

import type {
  DetectedLoaders,
  OptimizedImagesConfig,
} from '@vitus-labs/tools-nextjs-images'

On this page