ROADMAP
March 24, 2026 · View on GitHub
Development roadmap for vite-font-extractor-plugin — v3.0.
Priorities: P0 — blocks release, P1 — next release, P2 — planned, P3 — backlog.
Open tasks
Vite 8 (Rolldown) — Full Support
- Priority: P0
- Status: Experimental for
?subset=feature. Icon font minification works. Subset has known issues.
What works on Vite 8:
- Icon font minification (ligatures, raws) — fully functional
- Content-based font hashing — generates correct hashed file names
generateBundleasset replacement — compatible with Rolldown's API- Dev server font minification — middleware works
What doesn't work on Vite 8:
- CSS
?subset=query stripping —bundle.tsregex replacement doesn't match Rolldown's CSS output format.?subset=remains in final CSS URLs.- Root cause: Rolldown generates CSS differently than Rollup — URL encoding, whitespace, or quote handling differs
- Fix needed: investigate Rolldown's CSS output format and adapt regex in
bundle.tsstring asset replacement
- JS
?subset=via renderChunk — Rolldown inlines asset URLs as variable names (text_font_default) instead of string literals.renderChunkregex can't find URL patterns to strip?subset=.- Root cause: Rolldown's module linking resolves asset imports differently — uses variable references rather than string URLs in chunk code
- Fix needed: investigate Rolldown's asset import transformation. May need
resolveIdorloadhook instead ofrenderChunkfor Rolldown
- JS asset deduplication — same file with same
?subset=may not deduplicate identically across Rollup and Rolldown- Fix needed: test and adapt composite key logic for Rolldown's reference ID format
Steps to achieve full Vite 8 support:
- Build with Vite 8 and inspect raw CSS/JS output to understand Rolldown's exact format differences
- Adapt
bundle.tsCSS path replacement to handle Rolldown's output - Investigate alternative to
renderChunkfor JS subset stripping on Rolldown (possiblyresolveIdwithenforce: 'pre') - Add Vite 8-specific assertions in subset tests (not weaker — different)
- Remove "Experimental" label from README
Files: src/bundle.ts, src/render-chunk.ts, tests/subset.spec.ts, README.md
Testing
CSS Modules (.module.css)
- Priority: P2
- Vite natively supports CSS modules — verify
@font-faceinside.module.cssis processed by plugin - Files: create
tests/fixtures/css-modules/, add tests
Emoji / non-BMP Unicode in auto mode
- Priority: P2
- Auto mode uses
GLYPH_REGEXforcontent: "..."— verify emoji support (🔤, 🎵) and non-BMP characters (U+10000+) - Depends on fontext support
- Files: create
tests/fixtures/auto-emoji/, updatesrc/constants.tsif needed
Deterministic font hashing
- Priority: P1
- Status: Open issue
- fontext native encoders (ttf2woff2, ttf2eot) produce nondeterministic output — content-based hashing may differ between runs
- Tests use
retry: 5as workaround - Needed: investigate deterministic font subsetting or alternative hashing approach
Code Quality (from audit)
Type bundle parameter properly
- Priority: P2
src/extractor.ts:107—bundle as anybypasses type safety- Should use Rollup
OutputBundletype and handle both assets and chunks
Break down large functions
- Priority: P3
src/bundle.ts:15(144 lines),src/transform.ts:102(140 lines),src/minify.ts:26(76 lines)- Extract sub-functions for Google Font processing, string asset replacement, etc.
Features
JS import ?subset= in dev server
- Priority: P3
- Currently
renderChunkonly processes build mode - Dev server doesn't intercept
import font from './font.woff2?subset=ABC' - Needed: add handling in
configureServermiddleware
Completed (v3.0)
Infrastructure
.nvmrc (Node 24)Jest → VitestESLint → oxlint + oxfmtGit hooks (pre-commit, commit-msg).gitmessage (Conventional Commits)Changesets (automated CHANGELOG)CI pipeline (lint + test parallel)
Dependencies & Compatibility
All dependencies updated (fontext 1.10, TypeScript 5.9, etc)lodash → native implementationsfast-glob → node:fsVite 7 supportVite 8 (Rolldown) — icon font minification worksVite 4 deprecated → dropped@tsconfig/node20 → node22
Architecture
Decompose extractor.ts → 6 modulesPluginContext with explicit dependenciesContent-based font hashingRolldown-compatible asset pipeline (delete + emitFile)Proxy → explicit gettersnull as any → type-safe accessorsMath.random() → deterministic SID
Features
Font subsetting (?subset= in CSS and JS) — Vite 5/6/7renderChunk for JS import subset — Vite 5/6/7Google Fonts multi-family supportMultiple @font-face with same nameAuto cache cleanup when cache disabledGraceful degradation on minification errorsMultiple different ?subset= for same source file
Quality
Type safety: strict in tests, toError(), getLogger/getResolvers326 tests, 13 filesUnit tests for regex parsing (37 tests)Dev server testsError path testsPlugin options testsHash consistency testsFont import pattern tests (multi-weight, font-display, absolute path, dynamic import, new URL)Subset tests (chars, range, combined, JS import, config, multi, dedup)Logger tests (16 tests)Sass @import → @use migration
UX
Structured logger with progress bars and summaryPlayground — full feature showcaseREADME with badges, quick start, subsetting, troubleshooting