# How the Sharp Image Processing Library Integrates with next-export-optimize-images: Complete Technical Guide

> Learn how the sharp image processing library integrates with next-export-optimize-images. This guide details how sharp transforms images for optimized outputs using user configurations.

- Repository: [d-suke/next-export-optimize-images](https://github.com/dc7290/next-export-optimize-images)
- Tags: deep-dive
- Published: 2026-02-28

---

**The sharp image processing library integrates with next-export-optimize-images by serving as the core image transformation engine in the CLI, where it reads image buffers, applies auto-orientation and resizing, and encodes output to formats like JPEG, PNG, WebP, and AVIF based on user-defined configuration options.**

The `dc7290/next-export-optimize-images` repository leverages the high-performance sharp library to handle export-time image optimization for statically exported Next.js applications. Understanding how the sharp image processing library integrates with next-export-optimize-images reveals the architectural decisions that enable efficient format conversion, quality control, and caching during the build process.

## Architectural Overview of Sharp Integration

The integration follows a pipeline architecture where sharp operates as the underlying processing engine within the CLI workflow. The library is not invoked during the webpack build phase but rather during the post-build optimization step, ensuring that image buffers are processed after Next.js has emitted static assets.

### CLI Entry Point ([`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts))

The primary integration occurs in [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts), which serves as the optimization engine executed by the `next-export-optimize-images run` command. This module imports the sharp library directly at line 9:

```typescript
import sharp from 'sharp'

```

When processing begins, the code creates a sharp instance for each image buffer at line 91:

```typescript
const image = sharp(imageBuffer, { sequentialRead: true, animated: true })

```

The `sequentialRead: true` option optimizes memory usage for large images, while `animated: true` enables support for GIF and animated WebP processing.

### Configuration Schema ([`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts))

User customization of sharp behavior is governed by the configuration interface defined in [`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts). This module exposes a `sharpOptions` property that maps directly to sharp's native option objects. Lines 1-8 import the necessary types:

```typescript
import type { PngOptions, JpegOptions, WebpOptions, AvifOptions } from 'sharp'

```

Lines 69-78 define the configuration structure that allows per-format tuning:

```typescript
sharpOptions?: {
  png?: PngOptions
  jpg?: JpegOptions
  webp?: WebpOptions
  avif?: AvifOptions
}

```

This type-safe interface ensures that users can pass any valid sharp option (such as `compressionLevel` for PNG or `mozjpeg` for JPEG) directly to the processing pipeline.

## The Image Processing Pipeline

Once the CLI identifies images requiring optimization, sharp executes a standardized transformation pipeline for each asset.

### Instance Creation and Buffer Handling

The pipeline begins by reading the original image file into a Node.js Buffer. The CLI then initializes sharp with specific constructor options to handle both static and animated images efficiently:

```typescript
const image = sharp(imageBuffer, { sequentialRead: true, animated: true })

```

This configuration ensures that sharp processes images in a memory-efficient streaming manner while preserving animation frames for supported formats.

### Transformations: Auto-Orientation and Resizing

Before encoding, sharp applies two critical transformations to ensure visual consistency and performance:

1. **Auto-orientation**: The pipeline calls `image.rotate()` to automatically correct orientation based on EXIF data, ensuring that images display correctly regardless of how they were captured.

2. **Resizing**: The image is resized to the target width using `image.resize({ width, withoutEnlargement: true })`. The `withoutEnlargement: true` parameter prevents sharp from upscaling images beyond their original dimensions, preserving quality and reducing file bloat.

### Format-Specific Encoding Logic

The final pipeline stage involves encoding the transformed image into the target format. The CLI implements a switch-based dispatcher that selects the appropriate sharp method based on the requested output format:

```typescript
// JPEG / JPG
const jpeg = await image.jpeg({ quality, ...sharpOptions?.jpg })
// PNG
const png  = await image.png({ quality, ...sharpOptions?.png })
// WebP
const webp = image.webp({ quality, ...sharpOptions?.webp })
// AVIF
const avif = image.avif({ quality, ...sharpOptions?.avif })

```

Each method receives the user-defined quality setting and any additional format-specific options from the `sharpOptions` configuration. The results are then written to both a cache location and the final output directory using `toFile()`:

```typescript
await jpeg.toFile(outputPath)

```

This dual-write strategy enables the caching mechanism to skip redundant sharp processing when image hashes match in subsequent builds.

## Configuring Sharp via export-images.config.js

Developers can customize sharp behavior by creating an [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) file in the project root. This configuration file exports an object that conforms to the schema defined in [`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts):

```javascript
// export-images.config.js
module.exports = {
  quality: 80,               // default quality for all formats
  sharpOptions: {
    // PNG-specific options (see https://sharp.pixelplumbing.com/api-output#png)
    png: { compressionLevel: 9, adaptiveFiltering: true },

    // JPEG-specific options (see https://sharp.pixelplumbing.com/api-output#jpeg)
    jpg: { mozjpeg: true, progressive: true },

    // WebP-specific options (see https://sharp.pixelplumbing.com/api-output#webp)
    webp: { lossless: false, alphaQuality: 80 },

    // AVIF-specific options (see https://sharp.pixelplumbing.com/api-output#avif)
    avif: { lossless: false, speed: 4 },
  },
};

```

The CLI merges these options with the per-format calls using the spread operator (`...sharpOptions?.jpg`), ensuring that any omitted properties fall back to sharp's internal defaults.

## Build Pipeline Integration

While sharp operates exclusively within the CLI optimization phase, the library ensures image assets are prepared for processing through two complementary mechanisms that bridge the Next.js build and the post-build optimization.

### Webpack Loader Preparation ([`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts))

The runtime loader located in [`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts) rewrites image import statements during the Next.js build, ensuring that image files are emitted as static assets in the output directory. These emitted files serve as the source buffers that the CLI later processes with sharp. While this loader does not invoke sharp directly, it supplies the file paths and manifest entries required for the optimization pipeline.

### Post-Build Hook ([`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts))

The `withExportImages` wrapper in [`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts) modifies the Next.js webpack configuration to inject the optimization loader and ensures that the CLI runs after the static export completes. This module bridges the build and optimization phases, guaranteeing that image assets are fully emitted before sharp processes them. It does not interact with sharp directly but orchestrates the environment where sharp operates.

## Summary

- **Sharp serves as the core processing engine** in [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts), handling all image transformations during the export optimization phase.
- **Instance initialization** uses `sharp(imageBuffer, { sequentialRead: true, animated: true })` to support both static and animated images with memory-efficient processing.
- **Configuration flexibility** is provided through `sharpOptions` in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js), allowing per-format tuning of JPEG, PNG, WebP, and AVIF output.
- **Pipeline architecture** separates asset preparation (webpack loader) from image processing (CLI), with sharp operating exclusively in the post-build optimization step.
- **Performance optimizations** include caching processed images to skip redundant sharp operations and using `withoutEnlargement: true` to prevent quality degradation.

## Frequently Asked Questions

### How does next-export-optimize-images use Sharp to process different image formats?

The library dispatches to format-specific sharp methods based on the target output type. In [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts), the code calls `image.jpeg()`, `image.png()`, `image.webp()`, or `image.avif()` depending on the requested format, passing quality settings and user-defined options from `sharpOptions`. Each method returns a processed image buffer that is written to the output directory using `toFile()`.

### Can I customize Sharp compression settings for specific image formats?

Yes, you can define format-specific options in your [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) file under the `sharpOptions` key. The configuration accepts `PngOptions`, `JpegOptions`, `WebpOptions`, and `AvifOptions` interfaces from sharp, allowing you to set properties like `compressionLevel` for PNG, `mozjpeg` for JPEG, or `speed` for AVIF. These options are merged with the default quality settings during processing.

### Does the Sharp integration support animated images like GIFs?

Yes, the sharp integration explicitly supports animated images. When creating the sharp instance in [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts), the code passes `{ animated: true }` to the constructor alongside `sequentialRead: true`. This enables sharp to process multi-frame images such as GIFs and animated WebP files, preserving animation data during resizing and format conversion.

### Where in the codebase does the actual Sharp image processing occur?

All direct sharp processing occurs in [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts), which serves as the CLI optimization engine. This file imports the sharp library at line 9, instantiates it with image buffers at line 91, applies transformations like rotation and resizing, and handles format-specific encoding. While [`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts) defines the sharp options interface and [`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts) prepares the assets, the actual pixel manipulation happens exclusively within the CLI index module.