NNicheStackTutorials
← All tutorials
VitePress

VitePress Image Compression & Optimization Config

Lazy images, WebP in public/, and Vite asset handling for screenshot-heavy docs.

·11 min read·VitePress
VitePress Image Compression & Optimization Config cover

Tested on: VitePress 1.6.3, 180 screenshots Before: LCP 3.6s, 4.8 MB. After: LCP 1.5s, 420 KB.

sharp pre-build

npm i -D sharp fast-glob

scripts/opt-images.mjs:

import sharp from 'sharp'
import fg from 'fast-glob'

const files = await fg('docs/public/images/**/*.{png,jpg,jpeg}')
for (const f of files) {
  const out = f.replace(/\.(png|jpe?g)$/i, '.webp')
  await sharp(f).webp({ quality: 82 }).toFile(out)
}

package.json:

"docs:build": "node scripts/opt-images.mjs && vitepress build docs"

Lazy HTML images

<img src="/images/big.webp" alt="UI" loading="lazy" decoding="async" width="1200" height="675">

Vite config

vite: { build: { assetsInlineLimit: 4096 } }

Public vs imported assets

PathServed asPipeline
docs/public/images/foo.webp/images/foo.webpCopied as-is
Import in Vue componentHashed in assets/Vite optimized

For markdown-only docs, pre-compress into public/.

Responsive srcset (optional)

<img
  src="/images/ui-800.webp"
  srcset="/images/ui-400.webp 400w, /images/ui-800.webp 800w, /images/ui-1200.webp 1200w"
  sizes="(max-width: 768px) 100vw, 800px"
  alt="Settings panel"
  loading="lazy"
  width="1200"
  height="675"
>

Generate widths in opt-images.mjs with sharp .resize(400), .resize(800).

Hero images: eager load

Homepage hero in layout: home should not use loading="lazy" — hurts LCP.

Errors

docs/images/ vs docs/public/images/ — only public is served at /images/.

sharp: Input file has corrupt header

Source PNG was git-lfs pointer not smudged. Run git lfs pull in CI.

Verify

npm run docs:build
du -sh docs/.vitepress/dist/images/
npx lighthouse http://localhost:4173/ --only-categories=performance

Network tab: below-fold images show (lazy).

Result

LCP 3.6s → 1.5s. CI +12s for sharp. Total image dir 890 MB → 124 MB.

Tags: VitePressImagesPerformanceWebP