WebP image output in a Webpack build
How to enable WebP-only image output in a Webpack build (TypeScript + React)
This setup converts .png/.jpg/.jpeg to WebP during the build and makes existing import x from "./img.png" usages end up pointing to WebP automatically (no fallback).
Step 1) Install the image tooling
Using imagemin:
npm i -D image-minimizer-webpack-plugin imagemin imagemin-webp
( ImageMinimizerWebpackPlugin supports multiple engines; this uses imagemin + imagemin-webp. (webpack ))
Step 2) Ensure Webpack emits image imports as files
Use Asset Modules (Webpack 5) to handle your imports. (webpack )
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g)$/i,
type: "asset/resource",
generator: {
// force webp extension in output filenames
filename: "images/[name].[contenthash].webp",
},
},
],
},
};
Step 3) Add a WebP generator via ImageMinimizerWebpackPlugin
Webpack’s ImageMinimizerWebpackPlugin supports a generator preset (e.g. "webp") using imageminGenerate and imagemin-webp. (webpack
)
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
"...",
new ImageMinimizerPlugin({
generator: [
{
preset: "webp",
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [["imagemin-webp", { quality: 80 }]],
},
},
],
}),
],
},
};
Step 4) Automatically rewrite .png/.jpg imports to request WebP (no code changes)
The plugin supports selecting a generator preset via an as=... query (e.g. ?as=webp). (webpack
)
Instead of editing your TS/TSX imports, have Webpack rewrite requests at bundle time:
const webpack = require("webpack");
module.exports = {
plugins: [
new webpack.NormalModuleReplacementPlugin(
/\.(png|jpe?g)(\?.*)?$/i,
(resource) => {
// append as=webp safely
if (/\bas=webp\b/.test(resource.request)) return;
resource.request += resource.request.includes("?") ? "&as=webp" : "?as=webp";
}
),
],
};
Now your existing code like:
import hero from "./hero.png";
will resolve as if it were:
import hero from "./hero.png?as=webp";
…and the emitted file/URL will be WebP.
Step 5) Add TypeScript module declarations (if you don’t already have them)
// images.d.ts
declare module "*.png" { const src: string; export default src; }
declare module "*.jpg" { const src: string; export default src; }
declare module "*.jpeg" { const src: string; export default src; }
(You don’t need *.webp typings if your source imports remain .png/.jpg.)
Step 6) Build and verify
- Run a production build
- Confirm
dist/images/...webpexists - Confirm your JS bundles reference
.webpURLs
Notes (so you don’t get surprised)
- This affects only images that go through Webpack’s module graph (TS/TSX imports, CSS
url()processed by Webpack, etc.). Hardcoded strings like"/img/foo.png"won’t be rewritten. - “No fallback” means older browsers without WebP support will not display images.
If you paste your current module.rules for images (and whether you use file-loader or asset modules already), I can provide a drop-in diff against your existing config.