Skip to main content
Asset modules allow you to use asset files (fonts, icons, images, etc.) without configuring additional loaders.

Asset Module Types

Webpack 5 provides four asset module types:
TypeDescriptionOld Equivalent
asset/resourceEmits file and exports URLfile-loader
asset/inlineExports data URIurl-loader
asset/sourceExports source coderaw-loader
assetAuto-chooses between resource and inlineurl-loader with limit
Asset modules are built into webpack 5. No need to install additional loaders.

Basic Usage

1

Configure asset module types

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg|gif|svg)$/,
        type: 'asset/resource'
      }
    ]
  }
};
2

Import assets in your code

import logo from './images/logo.png';

const img = document.createElement('img');
img.src = logo;
document.body.appendChild(img);
3

Configure output location

module.exports = {
  output: {
    assetModuleFilename: 'assets/[hash][ext][query]'
  }
};

asset/resource

Emits files to the output directory and returns the URL:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg|gif)$/,
        type: 'asset/resource'
      }
    ]
  },
  output: {
    assetModuleFilename: 'images/[hash][ext][query]'
  }
};
Usage:
import imageUrl from './photo.jpg';
// imageUrl is: 'images/a1b2c3d4.jpg'
Use asset/resource for large images, videos, and other files that should be loaded separately.

asset/inline

Inlines assets as data URIs:
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        type: 'asset/inline'
      }
    ]
  }
};
Usage:
import svgData from './icon.svg';
// svgData is: 'data:image/svg+xml;base64,...'
Inlining large files increases bundle size. Only inline small assets (< 8-10 KB).

asset/source

Imports the raw source code of the asset:
module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        type: 'asset/source'
      }
    ]
  }
};
Usage:
import textContent from './data.txt';
// textContent is the text file content as a string
console.log(textContent);

asset (Automatic)

Automatically chooses between inline and resource based on file size:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif|svg)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024 // 8kb
          }
        }
      }
    ]
  }
};
Behavior:
  • Files < 8 KB: Inlined as data URI
  • Files ≥ 8 KB: Emitted as separate files
The asset type is the most versatile. It optimizes automatically based on file size.

Custom Output Filenames

Global Configuration

module.exports = {
  output: {
    assetModuleFilename: 'assets/[name]-[hash][ext][query]'
  }
};

Per-Rule Configuration

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg)$/,
        type: 'asset/resource',
        generator: {
          filename: 'images/[hash][ext][query]'
        }
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name][ext]'
        }
      }
    ]
  }
};

Filename Placeholders

PlaceholderDescription
[name]Original filename
[hash]Content hash
[ext]Extension with dot
[query]Query string
[path]Original path
[contenthash]Content hash (alias)
Example:
generator: {
  filename: 'assets/[path][name]-[hash:8][ext]'
}

Common Asset Types

Images

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|jpeg|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024
          }
        },
        generator: {
          filename: 'images/[hash][ext][query]'
        }
      }
    ]
  }
};

SVG

module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        type: 'asset/inline',
        generator: {
          dataUrl: content => {
            content = content.toString();
            return `data:image/svg+xml,${encodeURIComponent(content)}`;
          }
        }
      }
    ]
  }
};

Fonts

module.exports = {
  module: {
    rules: [
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name][ext]'
        }
      }
    ]
  }
};
Usage in CSS:
@font-face {
  font-family: 'MyFont';
  src: url('./fonts/myfont.woff2') format('woff2');
}

Data Files

module.exports = {
  module: {
    rules: [
      {
        test: /\.(json|xml|csv)$/,
        type: 'asset/source'
      }
    ]
  }
};

Public Path

Set the base path for assets in production:
module.exports = {
  output: {
    publicPath: 'https://cdn.example.com/',
    assetModuleFilename: 'assets/[hash][ext]'
  }
};
Result:
import logo from './logo.png';
// logo is: 'https://cdn.example.com/assets/a1b2c3d4.png'
The publicPath is prepended to all asset URLs. Use it when serving assets from a CDN.

Custom Data URL

Customize how data URIs are generated:
module.exports = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        type: 'asset/inline',
        generator: {
          dataUrl: content => {
            const svgContent = content.toString();
            // Optimize or transform SVG
            return `data:image/svg+xml;utf8,${encodeURIComponent(svgContent)}`;
          }
        }
      }
    ]
  }
};

Migration from Loaders

From file-loader

Before:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: ['file-loader']
      }
    ]
  }
};
After:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        type: 'asset/resource'
      }
    ]
  }
};

From url-loader

Before:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192
            }
          }
        ]
      }
    ]
  }
};
After:
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8192
          }
        }
      }
    ]
  }
};

From raw-loader

Before:
module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        use: 'raw-loader'
      }
    ]
  }
};
After:
module.exports = {
  module: {
    rules: [
      {
        test: /\.txt$/,
        type: 'asset/source'
      }
    ]
  }
};
Asset modules are simpler and faster than the old loader approach. Migrate when upgrading to webpack 5.

Complete Example

const path = require('path');

module.exports = {
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].[contenthash].js',
    assetModuleFilename: 'assets/[hash][ext][query]',
    publicPath: '/'
  },
  module: {
    rules: [
      // Images - auto inline if < 8kb
      {
        test: /\.(png|jpg|jpeg|gif|webp)$/,
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024
          }
        },
        generator: {
          filename: 'images/[hash][ext][query]'
        }
      },
      // SVG - inline as data URI
      {
        test: /\.svg$/,
        type: 'asset/inline'
      },
      // Fonts - always separate files
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name][ext]'
        }
      },
      // Text/data files - raw content
      {
        test: /\.(txt|md)$/,
        type: 'asset/source'
      }
    ]
  }
};