The Next.js <Image /> experience, now in Vite.
- Bring the power of Next.js's automatic image optimization to your Vite projects.
- Dedicated to the Vite + React ecosystem.
Simply add the plugin to your config, and start using the <Image /> component immediately. No complex setups, just performant images.
- ⚡ Next.js-like Experience: Familiar Image API for those coming from Next.js.
- 🖼️ Zero-Config Optimization: Automatic format conversion, resizing, and compression via
vite-imagetools. - 🎨 Built-in LQIP: Automatic Low Quality Image Placeholders (blur effect) while loading.
- 📱 Responsive Ready: Auto-generated
srcSetandsizesfor all viewports. - 🎯 Type-Safe: Full TypeScript support with tight integration.
Add it to vite.config.ts, and use it like this:
Option 1: Using query string (default)
// vite.config.ts
import { defineConfig } from "vite";
import { viteImage } from "@son426/vite-image/plugin";
export default defineConfig({
plugins: [
viteImage(), // Default breakpoints: [640, 1024, 1920]
],
});
// Component
import Image from "@son426/vite-image/react";
import myBg from "./assets/background.jpg?vite-image";
export default function Page() {
return (
<Image
src={myBg}
alt="Optimized Background"
fill
priority
placeholder="blur"
/>
);
}Option 2: Auto-apply without query string
// vite.config.ts
import { defineConfig } from "vite";
import { viteImage } from "@son426/vite-image/plugin";
export default defineConfig({
plugins: [
viteImage({
autoApply: {
extensions: [".jpg"],
},
}),
],
});
// Component
import Image from "@son426/vite-image/react";
import myBg from "./assets/background.jpg"; // No query needed
export default function Page() {
return (
<Image
src={myBg}
alt="Optimized Background"
fill
priority
placeholder="blur"
/>
);
}Note: For auto-apply, you'll need to add type declarations. See the TypeScript Setup section below.
Install the package. vite-imagetools and @rollup/pluginutils are included as dependencies.
pnpm add @son426/vite-image
# or
npm install @son426/vite-image
# or
yarn add @son426/vite-imageJust a standard Vite + React project.
- vite (>= 4.0.0)
- react (>= 18.0.0)
- react-dom (>= 18.0.0)
If you are using TypeScript, add the following to your project's type definition file (e.g., src/vite-env.d.ts):
/// <reference types="vite/client" />
/// <reference types="@son426/vite-image/client" />This ensures TypeScript recognizes ?vite-image imports.
Add the plugin to your vite.config.ts:
import { defineConfig } from "vite";
import { viteImage } from "@son426/vite-image/plugin";
export default defineConfig({
plugins: [
viteImage(), // Default: breakpoints [640, 1024, 1920], no autoApply
],
});Default configuration:
breakpoints: [640, 1024, 1920]autoApply: undefined(requires?vite-imagequery)
Custom breakpoints:
viteImage({
breakpoints: [800, 1200, 1920],
});Auto-apply without query string:
viteImage({
autoApply: {
extensions: [".jpg", ".png", ".webp"],
include: ["src/assets/**"],
exclude: ["src/icons/**"],
},
});Note: include and exclude patterns are matched against actual image file paths (after alias resolution). For example, @/assets/image.jpg resolves to src/assets/image.jpg.
With vite-imagetools options:
viteImage({
breakpoints: [640, 1024, 1920],
autoApply: {
extensions: [".jpg", ".png"],
include: ["src/**"],
},
imagetools: {
// vite-imagetools options
defaultDirectives: (url) => {
if (url.searchParams.has("vite-image")) {
return new URLSearchParams("format=webp");
}
},
},
});The ?vite-image query parameter automatically generates all required image data. When using ?vite-image, the src prop must be an object (not a string).
import Image from "@son426/vite-image/react";
import bgImage from "@/assets/image.webp?vite-image";
function MyComponent() {
return <Image src={bgImage} fill={false} alt="Description" />;
}Without query string (autoApply enabled):
// vite.config.ts
viteImage({
autoApply: {
extensions: [".jpg", ".png"],
include: ["src/assets/**"],
},
});
// Add type declarations for autoApply extensions
// In your project's vite-env.d.ts or a custom .d.ts file:
interface ResponsiveImageData {
src: string;
width: number;
height: number;
srcSet?: string;
blurDataURL?: string;
}
declare module "*.jpg" {
const imageData: ResponsiveImageData;
export default imageData;
}
declare module "*.png" {
const imageData: ResponsiveImageData;
export default imageData;
}
// Component
import bgImage from "@/assets/background.jpg"; // No query needed
<Image src={bgImage} alt="Background" />;Important:
- The
srcprop must receive the imported object directly. String URLs are not supported. - When using
autoApply, you need to add type declarations for the extensions you're using in your project's type definition file (e.g.,vite-env.d.ts).
The ?vite-image query (or autoApply) automatically generates:
src: Optimized image URLsrcSet: Responsive srcSet stringblurDataURL: Low Quality Image Placeholder (base64 inline)widthandheight: Image dimensions
Basic usage:
import Image from "@son426/vite-image/react";
import heroImage from "@/assets/hero.jpg?vite-image";
<Image src={heroImage} alt="Hero" />;Fill mode (container-filling images):
<div style={{ position: "relative", width: "100%", height: "400px" }}>
<Image src={bgImage} fill alt="Background" />
</div>With priority (LCP images):
<Image src={heroImage} alt="Hero" priority />With blur placeholder:
<Image src={heroImage} alt="Hero" placeholder="blur" />Without placeholder:
<Image src={heroImage} alt="Hero" placeholder="empty" />Custom data URL placeholder:
<Image src={heroImage} alt="Hero" placeholder="data:image/jpeg;base64,..." />Custom sizes:
<Image src={heroImage} alt="Hero" sizes="(max-width: 768px) 100vw, 50vw" />With onLoad and onError callbacks:
<Image
src={heroImage}
alt="Hero"
onLoad={(e) => console.log("Image loaded", e)}
onError={(e) => console.error("Image failed to load", e)}
/>With decoding:
<Image src={heroImage} alt="Hero" decoding="sync" />With overrideSrc (SEO optimization):
<Image
src={heroImage}
alt="Hero"
overrideSrc="/original-image.jpg"
/>Note: When
overrideSrcis provided, thesrcattribute uses the override value for SEO purposes, while the optimizedsrcSetis disabled. Placeholders are also disabled when usingoverrideSrc.
Combined usage:
<div style={{ position: "relative", width: "100%", height: "600px" }}>
<Image
src={heroImage}
alt="Hero"
fill
priority
placeholder="blur"
className="rounded-lg"
onLoad={(e) => console.log("Loaded")}
/>
</div>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
src |
ResponsiveImageData |
Yes | - | Image data object from ?vite-image query or autoApply |
fill |
boolean |
No | false |
Fill container mode (requires parent with position: relative) |
sizes |
string |
No | auto | Sizes attribute (auto-calculated from srcSet if not provided) |
priority |
boolean |
No | false |
High priority loading (preload + eager + fetchPriority high) |
placeholder |
'empty' | 'blur' | string |
No | 'empty' |
Placeholder type: 'empty' (none), 'blur' (blurDataURL), or data URL |
decoding |
'async' | 'sync' | 'auto' |
No | 'async' |
Image decoding strategy (Next.js Image compatible) |
overrideSrc |
string |
No | - | Override src attribute for SEO while using optimized images |
onLoad |
(event: React.SyntheticEvent<HTMLImageElement>) => void |
No | - | Callback fired when image loads successfully |
onError |
(event: React.SyntheticEvent<HTMLImageElement>) => void |
No | - | Callback fired when image fails to load |
className |
string |
No | - | Additional CSS classes |
style |
CSSProperties |
No | - | Additional inline styles |
...props |
ImgHTMLAttributes |
No | - | All standard img element attributes |
Notes:
- The
srcprop must be an object imported from?vite-imagequery or viaautoApply. String URLs are not supported. - The
widthandheightare automatically extracted from thesrcobject. - When
priority={true}, the image is preloaded usingreact-dom'spreloadAPI and loaded withloading="eager"andfetchPriority="high". - When
sizesis not provided, it's automatically calculated fromsrcSetbreakpoints. - When
overrideSrcis provided, thesrcattribute uses the override value (useful for SEO), whilesrcSetandsizesare disabled. Placeholders are also disabled. - The
decodingprop controls how the browser decodes the image:"async"(default, non-blocking),"sync"(blocking), or"auto"(browser decides).
The type returned from ?vite-image query or autoApply:
interface ResponsiveImageData {
src: string;
width: number;
height: number;
srcSet?: string;
blurDataURL?: string; // Base64 encoded blur placeholder (Next.js Image compatible)
}Type definitions are included. The package also extends vite-imagetools types for better TypeScript support:
import Image from "@son426/vite-image/react";
import type { ImageProps } from "@son426/vite-image/react";Note: When using autoApply with custom extensions, you need to define the ResponsiveImageData interface in your type definition file (as shown in the "Without query string" section above) since .d.ts files cannot use imports.
-
Image Processing: When you import an image with
?vite-imagequery or viaautoApply, the plugin automatically generates:- Responsive srcSet (default: 640px, 1024px, 1920px widths, customizable via
breakpoints) - Image metadata (largest breakpoint width)
- Blur placeholder (20px width, blurred, low quality, inline base64 as
blurDataURL)
- Responsive srcSet (default: 640px, 1024px, 1920px widths, customizable via
-
Image Component: The
<Image />component handles:- Automatic
sizescalculation fromsrcSetbreakpoints - Placeholder display (
blur,empty, or custom data URL) - Priority loading with
react-dom'spreloadAPI whenpriority={true} - Responsive image loading with srcSet
- Proper aspect ratio maintenance
- Fill mode for container-filling images
- Automatic
MIT