# How to Convert Images (PNG to WebP/AVIF) During Next.js Build

> Convert PNG to WebP and AVIF images during your NextJS build. Use next-export-optimize-images to automatically generate optimized assets and improve website performance.

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

---

**Use `next-export-optimize-images` to declare format conversions in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) and the library automatically generates WebP and AVIF assets during the Next.js build process.**

Converting PNG images to modern formats like WebP and AVIF during static site generation is essential for web performance. The `next-export-optimize-images` library handles this conversion automatically by integrating Sharp into the Next.js webpack pipeline. This guide explains how to configure the plugin to convert images from PNG to WebP and AVIF formats during build time.

## Configure Format Conversion in export-images.config.js

The conversion behavior is controlled through an [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) file in your project root. According to the source code in [[`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts), the library reads the `convertFormat` and `generateFormats` options to determine output formats.

```js
// export-images.config.js
module.exports = {
  /** Convert every PNG to WebP and AVIF */
  convertFormat: [
    // [sourceExtension, targetExtension]
    ['png', 'webp'],
    ['png', 'avif'],
  ],

  /** Always generate WebP & AVIF versions for all images */
  generateFormats: ['webp', 'avif'],

  /** Optional: quality (0-100) for the generated files */
  quality: 80,

  /** Optional: Sharp-specific options */
  sharpOptions: {
    webp: { quality: 80 },
    avif: { quality: 50 },
  },
};

```

### Understanding convertFormat vs generateFormats

These two configuration options serve different purposes during the build:

- **`convertFormat`**: Replaces the original file extension. When you specify `['png', 'webp']`, the optimizer treats the image as a WebP file instead of PNG, effectively converting the primary format.
- **`generateFormats`**: Creates additional copies in the specified formats while keeping the primary output. This is useful for providing fallback formats via the HTML `<picture>` element.

## Integrate the Plugin with Next.js

After creating the configuration file, wrap your Next.js configuration with `withExportImages` in [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js). This function, defined in [[`src/withExportImages.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/withExportImages.ts#L73-L104), injects a custom webpack loader required for the optimization pipeline.

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

module.exports = withExportImages({
  images: {
    // Required: keep the custom loader
    loader: 'custom',
  },
});

```

For TypeScript projects using ES modules, use the `.mjs` extension:

```js
// next.config.mjs
import withExportImages from 'next-export-optimize-images';

export default withExportImages({
  images: {
    loader: 'custom',
  },
});

```

## How the Build Pipeline Processes Images

The conversion happens during the webpack phase of `next build` or `next export` through three core components:

### 1. Configuration Resolution

The `getConfig` function in [[`src/utils/getConfig.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/getConfig.ts#L80-L94) validates and exposes your `convertFormat` settings to the build pipeline.

### 2. Output Path Generation

For each image processed, the `buildOutputInfo` function in [[`src/utils/buildOutputInfo.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/buildOutputInfo.ts)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/buildOutputInfo.ts) determines the final file extensions:

- It checks if the source extension matches any entry in `config.convertFormat` (lines 50-60)
- If matched, it replaces the extension variable with the target format (e.g., `png` becomes `webp`)
- It then merges `config.generateFormats` with the primary extension to create an array of output formats
- For each format, it generates the final output path and returns metadata including `{output, src, extension, originalExtension}`

### 3. Sharp Optimization Execution

The CLI optimizer in [[`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts#L14-L25) walks the manifest of images and calls Sharp to write each format to disk:

```typescript
// Simplified logic from src/cli/index.ts
case 'webp':
  await image.webp({ quality, ...sharpOptions }).toFile(outputPath);
  break;
case 'avif':
  await image.avif({ quality, ...sharpOptions }).toFile(outputPath);
  break;

```

A single source file like `hero.png` produces multiple optimized assets in the configured `imageDir` (default: `_next/static/chunks/images`):

```

_next/static/chunks/images/hero_800.webp
_next/static/chunks/images/hero_800.avif

```

## Render Images with Automatic Format Selection

The library provides a `Picture` component in [[`src/components/client/picture.tsx`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/components/client/picture.tsx)](https://github.com/dc7290/next-export-optimize-images/blob/main/src/components/client/picture.tsx) that automatically renders a `<picture>` element with `<source>` tags for each generated format.

```tsx
import { Picture } from 'next-export-optimize-images';

export default function Hero() {
  return (
    <Picture
      src="/hero.png"
      width={800}
      height={600}
      alt="Hero image"
      className="rounded"
    />
  );
}

```

This component reads the build manifest and outputs markup that allows browsers to select the best supported format:

```html
<picture>
  <source srcset="_next/static/chunks/images/hero_800.avif" type="image/avif">
  <source srcset="_next/static/chunks/images/hero_800.webp" type="image/webp">
  <img src="_next/static/chunks/images/hero_800.png" alt="Hero image" width="800" height="600">
</picture>

```

## Summary

- **Declare conversions** in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) using the `convertFormat` array to specify source-to-target mappings like PNG to WebP or AVIF.
- **Integrate** the plugin via `withExportImages` in [`next.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/next.config.js) with `loader: 'custom'` required.
- **Automated processing** occurs during the build via `buildOutputInfo` (path logic) and `optimizeImages` (Sharp execution) in the CLI.
- **Multiple formats** are supported simultaneously through `generateFormats`, creating additional copies beyond the primary conversion.
- **Client-side rendering** uses the `Picture` component to automatically serve the optimal format based on browser support.

## Frequently Asked Questions

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

`convertFormat` replaces the original file format during the build (e.g., treating a PNG as a WebP file), while `generateFormats` creates additional copies in specified formats without replacing the primary output. Use `convertFormat` to migrate away from legacy formats, and `generateFormats` to provide modern fallbacks alongside originals.

### Can I convert JPEG images to AVIF using this method?

Yes. Add `['jpg', 'avif']` or `['jpeg', 'avif']` to the `convertFormat` array in your [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js). The `buildOutputInfo` function in [`src/utils/buildOutputInfo.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/utils/buildOutputInfo.ts) processes any extension pair defined in the configuration, not just PNG sources.

### How do I adjust the quality settings for converted WebP and AVIF files?

Set the global `quality` option (0-100) in [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) for all formats, or specify granular options in `sharpOptions`. For example, set `sharpOptions: { webp: { quality: 85 }, avif: { quality: 60 } }` to control compression levels per format. These options are passed directly to Sharp in [`src/cli/index.ts`](https://github.com/dc7290/next-export-optimize-images/blob/main/src/cli/index.ts).

### Does this plugin work with the Next.js App Router?

Yes. The plugin works with both the Pages Router and App Router (Next.js 13+). When using TypeScript with the App Router, import `withExportImages` in `next.config.mjs` and ensure your [`export-images.config.js`](https://github.com/dc7290/next-export-optimize-images/blob/main/export-images.config.js) is in the project root. The `Picture` component is compatible with React Server Components when imported appropriately.