# How to Configure Image Optimization During `next export` with next‑export‑optimize‑images

> Optimize images during next export by creating an export-images.config.js file and using the withExportImages plugin. Speed up your Next.js site.

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

---

**To configure image optimization during `next export`, create an [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) file in your project root and wrap your [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js) with the `withExportImages` plugin provided by `next-export-optimize-images`.**

The `dc7290/next-export-optimize-images` library enables the same image optimization pipeline that powers `next/image`, but specifically for static HTML exports. All configuration lives in an optional [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) (or `.cjs`) file that the library reads at build time and injects into both the Webpack loader and the CLI optimizer.

## Configuration Architecture

Understanding how the configuration flows through the build process helps you debug issues and leverage advanced features.

### The Wrapper Mechanism

The entry point is [`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts). When you wrap your Next.js config with `withExportImages`, the wrapper searches for `export-images.config.*` in your project root. If found, it writes the configuration as a temporary CommonJS module inside `node_modules/next-export-optimize-images/` so that both the Webpack loader and the standalone CLI can import it consistently.

### Webpack Loader Integration

During the production build, the custom loader ([`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts)) receives the configuration via `getConfig()` from [`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts). This loader intercepts every `next/image` import and builds a manifest ([`.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)) containing every image size, format, and destination that will be generated.

### CLI Optimization Pipeline

After the build finishes, the CLI ([`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts)) reads the manifest and calls `buildOutputInfo()` ([`src/utils/buildOutputInfo.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/buildOutputInfo.ts)) for each entry to compute final output paths, filenames, and conversion rules. Then `getOptimizeResult()` runs **sharp** to process images, respecting your `quality`, `sharpOptions`, `convertFormat`, and `generateFormats` settings.

## The [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) Configuration File

The library exports a `Config` type that defines all available options. Here is the complete configuration schema:

```typescript
export type Config = {
  outDir?: string;                    // Destination of static export (default: 'out')
  imageDir?: string;                  // Where optimized images live (default: '_next/static/chunks/images')
  cacheDir?: string;                  // Cache location (default: 'node_modules/.cache')
  ignorePaths?: string[];             // Paths under public/ to skip
  basePath?: string;                  // Must match next.config.js basePath
  externalImageDir?: string;           // For downloaded remote images (default: '_next/static/media')
  quality?: number;                    // JPEG/WEBP/AVIF quality 0-100 (default: 75)
  filenameGenerator?: Function;        // Custom naming logic
  sharpOptions?: {                     // Format-specific sharp settings
    png?: import('sharp').PngOptions;
    jpg?: import('sharp').JpegOptions;
    webp?: import('sharp').WebpOptions;
    avif?: import('sharp').AvifOptions;
  };
  convertFormat?: [string, string][];  // e.g., [['png', 'webp']]
  generateFormats?: ('webp' | 'avif')[]; // Additional formats to generate (default: ['webp'])
  sourceImageParser?: Function;        // Rewrite parsed image paths
  remoteImages?: string[] | Function; // URLs to download at build time
  remoteImagesDownloadsDelay?: number; // Rate limiting in ms
  processingConcurrency?: number;      // Parallel processing limit (default: 10)
  mode?: 'build' | 'export';          // 'export' for static, 'build' for next start
};

```

All fields are optional; the library provides sensible defaults for each.

## Step-by-Step Implementation

### 1. Create the Configuration File

Create [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) at your project root:

```javascript
// export-images.config.js
module.exports = {
  outDir: 'out',
  imageDir: '_next/static/chunks/images',
  quality: 80,
  convertFormat: [['png', 'webp']],
  generateFormats: ['webp', 'avif'],
  filenameGenerator: ({ path, name, width, extension }) => {
    return `${path}/${name}-${width}.${extension}`;
  },
  remoteImages: async () => {
    const res = await fetch('https://example.com/api/images');
    return res.json(); // ['https://cdn.example.com/img1.jpg', ...]
  },
  processingConcurrency: 20,
};

```

### 2. Wrap next.config.js

Modify your Next.js configuration to use the wrapper:

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

module.exports = withExportImages({
  images: {
    domains: ['example.com'],
  },
});

```

The wrapper automatically sets `images.loader = 'custom'` and injects a Webpack rule that replaces the built-in `next-image-loader` with `next-export-optimize-images-loader` (lines 74-96 in [`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts)).

### 3. Execute the Build Pipeline

Add a script to your [`package.json`](https://github.com/dc7290/next-export-optimize-images/blob/main/package.json):

```json
{
  "scripts": {
    "build": "next build",
    "export": "next export",
    "optimize-images": "next-export-optimize-images",
    "static": "npm run build && npm run export && npm run optimize-images"
  }
}

```

Running `npm run static` executes the full pipeline: Next.js builds the app, exports static HTML, and the CLI optimizes every referenced image according to your configuration.

## Advanced Configuration Examples

### Custom Filename Generation

For cache-busting or organizational purposes, implement a custom `filenameGenerator`:

```javascript
// export-images.config.js
const crypto = require('crypto');

module.exports = {
  filenameGenerator: ({ path, name, width, extension }) => {
    const hash = crypto
      .createHash('sha256')
      .update(`${path}/${name}`)
      .digest('hex')
      .slice(0, 8);
    return `${path}/${name}-${width}-${hash}.${extension}`;
  },
};

```

### Sharp Format Options

Pass format-specific options directly to the sharp library:

```javascript
module.exports = {
  sharpOptions: {
    webp: { effort: 6, preset: 'photo' },
    avif: { quality: 70, speed: 4 },
    jpg: { progressive: true, mozjpeg: true },
  },
};

```

### Remote Image Handling

Configure external images with rate limiting:

```javascript
module.exports = {
  remoteImages: [
    'https://cdn.example.com/logo.png',
    'https://cdn.example.com/banner.jpg',
  ],
  remoteImagesDownloadsDelay: 200, // 200ms between downloads
  externalImageDir: '_next/static/media',
};

```

## Summary

- **Configuration File**: Create [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) at the project root to define optimization settings.
- **Wrapper Integration**: Use `withExportImages` in [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js) to inject the custom Webpack loader and prepare the CLI environment.
- **Build Flow**: Run `next build && next export`, then execute `next-export-optimize-images` to process the manifest generated during the Webpack phase.
- **Processing**: The CLI ([`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts)) uses sharp to handle format conversion, quality settings, and concurrent processing according to your configuration.
- **Output**: Optimized images are written to the configured `imageDir` inside your static export folder, with automatic generation of WebP/AVIF variants if specified.

## Frequently Asked Questions

### Where does `next-export-optimize-images` read the configuration from?

The library looks for [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) or `export-images.config.cjs` in your project root. The `withExportImages` wrapper ([`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts)) loads this file and writes it as a temporary module inside `node_modules/next-export-optimize-images/` so that both the Webpack loader ([`src/loader/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/loader/index.ts)) and the CLI ([`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts)) can access the same configuration via `getConfig()` ([`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts)).

### Can I use this with `next start` instead of `next export`?

Yes. Set `mode: 'build'` in your [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js). This switches the library from static export mode to build mode, allowing you to use the same optimization pipeline with `next start` rather than generating a static `out/` directory.

### How do I handle external images from a CDN?

Use the `remoteImages` configuration option. Provide either a static array of URLs or an async function that returns URLs to download. The CLI ([`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts)) downloads these during the optimization phase, respecting the `remoteImagesDownloadsDelay` setting to avoid rate limits, and saves them to `externalImageDir` (default: `_next/static/media`).

### What is the difference between `convertFormat` and `generateFormats`?

`convertFormat` replaces the original format (e.g., converting PNG to WebP), while `generateFormats` creates additional copies alongside the original (e.g., keeping PNG but also generating WebP and AVIF versions). Use `convertFormat` for size reduction, and `generateFormats` when you need fallback formats for older browsers.