# How to Enable Build-Time Image Optimization with the `next-export-optimize-images` Next.js Plugin

> Learn to enable build-time image optimization for your Next.js app with next-export-optimize-images. Optimize images during your production build using Sharp.

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

---

**The `next-export-optimize-images` plugin enables build-time image optimization by replacing Next.js's default image loader with a custom Webpack loader that records image variants during the production build, then processes those images using Sharp via a post-build CLI command.**

The `next-export-optimize-images` package solves the challenge of optimizing images for static Next.js exports. This open-source plugin intercepts image processing during `next build` and generates pre-optimized static assets, allowing full use of Next.js Image components in statically exported sites without requiring a Node.js server runtime.

## How the Plugin Architecture Works

The plugin operates through a two-phase build process that separates image detection from image processing.

During the **build phase**, the plugin swaps Next.js's default **`next-image-loader`** with its own **`next-export-optimize-images-loader`** via the `withExportImages` wrapper. As Webpack processes your application, this custom loader records every image size and format that Next.js would request and writes a manifest to [`.next/next-export-optimize-images-list.nd.json`](https://github.com/dc7290/next-export-optimize-images/blob/main/.next/next-export-optimize-images-list.nd.json). According to the source code in [`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts), this recording only occurs when `isDev` is `false`, ensuring zero overhead during development.

In the **optimization phase**, the CLI command `next-export-optimize-images` (exposed via [`bin/index.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/bin/index.js)) reads the generated manifest and runs **Sharp** to resize, convert, and compress images according to your configuration. The optimized files are placed in your static output directory, ready for deployment.

Key architectural components include:

- **`withExportImages`** ([`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts)): The configuration wrapper that validates settings, copies `export-images.config.*` into the package directory, and injects the custom Webpack loader.
- **`getConfig`** ([`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts)): Safely loads and deserializes the optional [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js), including any function-based options like `filenameGenerator`.
- **Image Components** ([`image.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/image.js) / [`legacy/image.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/legacy/image.js)): Re-exports of Next.js's Image component that resolve to the optimized static assets at runtime.

## Installation and Configuration

Enable build-time image optimization by installing the package, wrapping your Next.js configuration, and extending your build script.

### 1. Install the Plugin

Add the package as a development dependency:

```bash
npm install -D next-export-optimize-images

```

### 2. Wrap Your Next.js Configuration

Import `withExportImages` in your [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js) and wrap your existing configuration. The wrapper is **asynchronous**, so you must `await` it or return a Promise:

```javascript
// next.config.js
const withExportImages = require('next-export-optimize-images')

module.exports = async () => {
  return withExportImages({
    output: 'export',  // Required for static export
    // ...other Next.js config
  })
}

```

If you use additional plugins like `@next/bundle-analyzer`, compose them asynchronously:

```javascript
const withExportImages = require('next-export-optimize-images')
const withAnalyzer = require('@next/bundle-analyzer')({ enabled: process.env.ANALYZE === 'true' })

module.exports = async () => {
  const config = await withExportImages({ output: 'export' })
  return withAnalyzer(config)
}

```

### 3. Extend the Build Script

Modify your [`package.json`](https://github.com/dc7290/next-export-optimize-images/blob/main/package.json) scripts to run the optimizer after the standard Next.js build:

```json
{
  "scripts": {
    "build": "next build && next-export-optimize-images"
  }
}

```

The second command reads the manifest generated by the loader in [`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts) and creates the optimized image assets in your output directory.

## Customizing Optimization Settings

Create an [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) (or `.cjs`) file in your project root to control output directories, quality settings, and format conversion. The `withExportImages` function copies this file into the package's `node_modules` directory so the loader can `require` it at build time.

```javascript
// export-images.config.js
module.exports = {
  outDir: 'out',                          // Static export output directory
  imageDir: '_next/static/chunks/images', // Optimized image destination
  quality: 80,                            // JPEG/WEBP quality (0-100)
  convertFormat: [['png', 'webp']],       // Convert PNG files to WEBP
  generateFormats: ['webp', 'avif'],      // Generate additional formats for <Picture>
  remoteImages: async () => {
    // Download and optimize external images before processing
    return ['https://example.com/logo.png']
  },
}

```

The `convertFormat` array accepts tuples of `[sourceFormat, targetFormat]` to transform images during optimization, while `generateFormats` creates modern format fallbacks for the Picture component.

## Using the Optimized Image Component

Import the Image component from the package instead of `next/image`. The component behaves identically to Next.js's native implementation but resolves to the pre-optimized static files generated during the build process.

```tsx
// pages/index.tsx
import Image from 'next-export-optimize-images/image'

export default function Home() {
  return (
    <>
      {/* Local public image */}
      <Image src="/images/hero.png" width={1920} height={1080} alt="Hero" />

      {/* Imported image with hashed filename */}
      import logo from '@/public/logo.png'
      <Image src={logo} alt="Logo" />

      {/* Remote image (downloaded at build time) */}
      <Image src="https://example.com/remote.jpg" width={800} height={600} alt="Remote" />
    </>
  )
}

```

At runtime, these components resolve to paths like `/_next/static/chunks/images/hero-1920.webp`, serving the optimized assets directly from your CDN or static host.

## Summary

- **`withExportImages`** wraps your [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js) to inject the custom Webpack loader during production builds.
- The **loader** ([`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts)) records image variants to [`.next/next-export-optimize-images-list.nd.json`](https://github.com/dc7290/next-export-optimize-images/blob/main/.next/next-export-optimize-images-list.nd.json) during the build.
- The **CLI** (`next-export-optimize-images`) processes the manifest using Sharp to generate optimized static assets.
- **[`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js)** provides granular control over quality, format conversion, and remote image handling.
- Import **Image** from `next-export-optimize-images/image` to serve the pre-optimized files in your application.

## Frequently Asked Questions

### How does the plugin handle remote images during build-time optimization?

The `remoteImages` configuration option in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) accepts an async function that returns an array of URLs. The plugin downloads these images before the optimization phase begins, allowing external assets to be processed with the same Sharp pipeline as local files.

### Can I use this plugin with other Next.js configuration wrappers?

Yes. Because `withExportImages` returns a Promise, you can compose it with other asynchronous plugins like `@next/bundle-analyzer`. Nest the calls by awaiting each wrapper sequentially, or use a composition utility to merge configurations.

### What image formats does the build-time optimizer support?

The plugin supports all formats handled by Sharp, including JPEG, PNG, WEBP, AVIF, and GIF. Use `convertFormat` to transform source files into alternative formats (e.g., PNG to WEBP), and `generateFormats` to create multiple format variants for responsive image fallbacks.

### Where are the optimized images stored after the build completes?

By default, optimized images are placed in `_next/static/chunks/images` within your output directory (configurable via the `imageDir` option in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js)). The manifest file at [`.next/next-export-optimize-images-list.nd.json`](https://github.com/dc7290/next-export-optimize-images/blob/main/.next/next-export-optimize-images-list.nd.json) tracks these locations during the build process.