The oh-image Vite image plugin lets you import optimized images as React components. It intercepts your image imports, processes them using Sharp, and generates responsive assets ready for the web.
Integration
To integrate the oh-image plugin into your project, add it to the plugins array in your vite.config.ts.
import { ohImage } from "@lonik/oh-image/plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [ohImage()],
});
Usage
The oh-image plugin does not automatically process every image in your project; it is an opt-in behavior.
To instruct the plugin to process an image, append the $oh query parameter to your import statement:
import SomeImage from "./assets/photo.jpg?$oh";
Important Caveat
Note: The plugin can only process images located within your project's source directory (e.g., src/assets/, src/images/).
Images placed in the public/ folder are served as-is by Vite and bypass the build process, meaning oh-image cannot optimize them. Move any images you wish to optimize into your src/ folder.
How it Works
When the plugin encounters an image import with the ?$oh query, it optimizes the image, generates necessary metadata (like dimensions and a placeholder), and wraps it in an <Image /> component.
The imported entity is a regular Image component that can be used directly in your application:
import SomeImage from "./assets/photo.jpg?$oh";
function App() {
return <SomeImage />;
}
Since SomeImage is a Image component, you can pass any standard Image props to it, in addition to the ones pre-configured by the plugin.
The plugin automatically sets the following properties for you:
widthheightsrcsrcSetplaceholder
Because the image is static, the plugin can pre-calculate these values during the build process.
Configuration
The plugin can be configured globally in your Vite config or locally via query parameters.
Local Configuration
You can override processing options on a per-import basis by adding additional query parameters.
// Convert to AVIF and apply a blur
import SomeImage from "./assets/photo.jpg?blur=50&format=avif&$oh";
function App() {
return <SomeImage />;
}
Global Configuration
You can configure the plugin in vite.config.ts to apply global defaults.
Note the nested structure for transforms and placeholder.
import { ohImage } from "@lonik/oh-image/plugin";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
ohImage({
distDir: "oh-images",
// Default transformations for the main image
transforms: {
format: "webp",
quality: 80,
},
// Breakpoints for responsive srcSet
breakpoints: [640, 768, 1024],
// Enable/Disable placeholder generation globally
pl_show: true,
// Default transformations for the placeholder image
placeholder: {
format: "webp",
blur: 20,
},
}),
],
});
Query Param Options
These options can be passed globally (within transforms object) or as query parameters.
When used as query parameters, they apply to the main image. To apply them to the placeholder, prefix the key with pl_ (e.g., pl_blur=10).
| Option | Type | Description |
|---|---|---|
[pl_]width | number | Target width for the processed image. |
[pl_]height | number | Target height for the processed image. |
[pl_]format | string | Output format (e.g., webp, avif, png). |
[pl_]quality | number | Change quality of the Image (1-100). |
[pl_]blur | number | Blur the image with the specified sigma. |
[pl_]flip | boolean | Flip the image vertically. |
[pl_]flop | boolean | Flop the image horizontally. |
[pl_]rotate | number | Rotate the image by the specified angle. |
[pl_]sharpen | number | Sharpen the image with the specified sigma. |
[pl_]median | number | Apply a median filter with the specified size. |
[pl_]gamma | number | Apply gamma correction. |
[pl_]negate | boolean | Negate the image colors. |
[pl_]normalize | boolean | Normalize the image contrast. |
[pl_]threshold | number | Apply a threshold with the specified value. |
pl_show | boolean | Generate a placeholder image ? (true/false). |
breakpoints | number[] | Comma-separated list of widths for srcSet. |
For more details on image operations, refer to the Sharp documentation.
Global-Only Options
In addition to the processing options, the global configuration accepts:
| Option | Type | Default | Description |
|---|---|---|---|
distDir | string | oh-images | The subdirectory within your build output where images will be saved. |
outDir | string | The directory relative to the project root where images will be saved, overriding Vite's build.outDir. |
Default Configuration
By default, the plugin uses the following settings:
{
distDir: "oh-images",
breakpoints: [16, 48, 96, 128, 384, 640, 750, 828, 1080, 1200, 1920],
pl_show: true,
transforms: {
format: "webp",
},
placeholder: {
quality: 10,
blur: 50,
format: "webp",
},
}
Passing Parameters via Query String
You can pass various data types as query parameters in your imports:
String
Pass the value directly.
import image from "./assets/image.png?format=png&$oh";
Number
Pass a numeric value.
import image from "./assets/image.png?blur=50&$oh";
Array
Pass comma-separated values.
import image from "./assets/image.png?breakpoints=16,32,64,128&$oh";
To pass an empty array (e.g., to disable breakpoints), pass the key without a value:
import image from "./assets/image.png?breakpoints&$oh";
Boolean
Pass true or false.
import image from "./assets/image.png?placeholder=true&$oh";
import image from "./assets/image.png?placeholder=false&$oh";
Unset a Value
Except boolean type, To unset a default option (effectively setting it to undefined or null), pass the key name only.
// Prevent Sharp from changing the format (uses original)
import image from "./assets/image.png?format&$oh";
Build vs. Dev Mode
The plugin operates differently depending on your environment to balance speed and performance.
Development (Lazy Processing)
In development, images are processed lazily. Images are only processed when requested by the browser and are cached in the Vite cache directory. This ensures fast startup times.
Production Build (Eager Processing)
During the build process, the plugin eagerly optimizes all imported images with $oh query parameter. It automatically generates the main image, responsive variants (srcSet), and placeholders based on your configuration.