Skip to content

Inconsistent UnoCSS icon bundling in v52+ (CSS size varies between ~68KB and ~94KB) #2477

@njncalub

Description

@njncalub

Describe the bug

In Slidev v52.9.0+, running slidev build slides.md --out dist produces inconsistent CSS bundle sizes regarding UnoCSS icons:

  • ~94KB CSS - Icons are included correctly
  • ~68KB CSS - Icons are missing (UnoCSS icon classes not bundled)

This causes invisible icons in the navigation bar similar to what was posted in #2300

Minimal reproduction

  1. Create a new Slidev project: npm create slidev@latest
  2. Build the project: slidev build slides.md --out dist
  3. Check CSS size: ls -lh dist/assets/*.css
  4. Delete dist and cache: rm -rf dist node_modules/.vite
  5. Build again: slidev build slides.md --out dist
  6. Check CSS size: ls -lh dist/assets/*.css

Expected: CSS size should be consistent across builds
Actual: CSS size fluctuates between ~68KB and ~94KB

Environment

  • Slidev version: v52.14.1
  • Working version: v51.8.2
  • Node version: Latest LTS
  • Package manager: npm
  • OS: OSX

Root Cause Analysis

The issue might be introduced in commit d9850f0 (Nov 18, 2025) - "feat: support .js extension and reduce sync fs operations (#2369)"

In packages/slidev/node/setups/unocss.ts:

v51.8.2 (working):

collections: {
  slidev: {
    logo: () => readFileSync(resolve(clientRoot, 'assets/logo.svg'), 'utf-8'),
  },
},

v52+ (broken):

collections: {
  slidev: {
    logo: () => readFile(resolve(clientRoot, 'assets/logo.svg'), 'utf-8'),
  },
},

Why This Causes Inconsistent Behavior

UnoCSS presetIcons() expects the collections function to return the SVG content synchronously. When readFile() (async) is used:

  1. The function returns a Promise<string> instead of string
  2. During build, UnoCSS may not properly await the Promise
  3. Timing differences cause inconsistent results:
    • Sometimes the Promise resolves before UnoCSS scans for icons → icons included (~94KB)
    • Sometimes it doesn't resolve in time → icons excluded (~68KB)

The ~26KB difference in CSS size corresponds to the UnoCSS icon styles that are conditionally included.

Additional Context

  • The issue persists even after clearing Vite cache
  • Running the same build command multiple times produces different results
  • No specific slide content triggers this - it's a timing issue
  • Also affected by commit 593b9f8 which changed config loading behavior

Possible Fix

Revert to using readFileSync for the logo collection, as UnoCSS requires synchronous content retrieval. The logo.svg file is tiny (~1-2KB), so sync I/O is acceptable for build-time setup.


Related commits:

  • d9850f0 - feat: support .js extension and reduce sync fs operations
  • 593b9f8 - fix: a better way to load setup files
  • f476a6c - feat: update Vite to v7

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions