UNPKG

vite-plugin-lqip

Version:

Low-quality image placeholder (LQIP) plugin for Vite.

67 lines (61 loc) 1.47 kB
import mime from 'mime'; import path from 'node:path'; import sharp from 'sharp'; import type { Plugin } from 'vite'; export interface LQIPPluginOptions { sharp?: { /** * (optional) Provide options to sharp.resize * @default { width: 32, height: 32, fit: 'inside', kernel: sharp.kernel.cubic } */ resize?: sharp.ResizeOptions; /** (optional) provide options to sharp.webp */ webp?: sharp.WebpOptions; /** * (optional) provide blur factor * @default 1.5 */ blur?: number; }; } export default function vitePluginLqip(options?: LQIPPluginOptions): Plugin { return { name: 'vite-plugin-lqip', enforce: 'pre', async load(id) { const [base, search] = id.split('?'); if (!search) { return null; } const s = new URLSearchParams(search); if (!s.has('lqip')) { return null; } const img = sharp(base); const metadata = await img.metadata(); const output = await img .toFormat('webp', { smartSubsample: true, ...options?.sharp?.webp, }) .blur(1.25) .resize({ width: 32, height: 32, fit: 'inside', kernel: sharp.kernel.cubic, ...options?.sharp?.resize, }) .toBuffer(); const lqip = `data:${mime.getType(path.extname(base!))};base64,${output.toString('base64')}`; return `import src from '${base}?url'; export default { lqip: \`${lqip}\`, src, width: ${metadata.width ?? -1}, height: ${metadata.height ?? -1}, }; `; }, }; }