| name | wsh-dependency-cleanup |
| description | Strategies for removing bloated WASM/JS dependencies in WSH 2026 — FFmpeg, ImageMagick, Web LLM, jQuery, moment, lodash, core-js, regenerator-runtime, and related replacements. |
WSH: Dependency Cleanup
Removing or replacing oversized dependencies is critical for TBT and bundle size. This project includes several multi-MB WASM libraries and unnecessary utility libraries.
Use this skill when removing @ffmpeg/ffmpeg, @imagemagick/magick-wasm, @mlc-ai/web-llm, jquery, moment, lodash, core-js, or other bloated deps.
Target Dependencies
@ffmpeg/ffmpeg + @ffmpeg/core (~44MB WASM)
- Used in:
client/src/utils/load_ffmpeg.ts, PausableMovie.tsx
- Purpose: GIF to video conversion on client side
- Replace with: Server-side conversion (ffmpeg CLI) or serve GIFs as-is with
<img> tag, or convert GIFs to MP4/WebM at build time
- Strategy: Pre-convert GIF files to MP4/WebM, serve as
<video> elements. If GIFs must stay dynamic, use a simpler GIF decoder or just use <img src="*.gif">
@imagemagick/magick-wasm (~8MB WASM)
- Used in:
client/src/utils/convert_image.ts
- Purpose: Client-side image format conversion (used in post creation)
- Replace with: Server-side Sharp for image processing, or canvas API for simple operations
- Strategy: Move image processing to server endpoint. Client sends raw file, server converts.
@mlc-ai/web-llm (~large, downloads model at runtime)
- Used in:
client/src/utils/create_translator.ts, TranslatableText.tsx
- Purpose: Client-side text translation
- Replace with: Server-side translation endpoint or remove feature if not scored
- Strategy: Check if translation is part of scoring. If not, stub it out. If yes, move to server.
jquery + jquery-binarytransport (~90KB)
- Used in:
client/src/utils/fetchers.ts (fetchBinary, fetchJSON, sendFile, sendJSON)
- Purpose: HTTP requests with
async: false (sync XHR)
- Replace with: Native
fetch() API (async)
- Critical: The
async: false is a HUGE TBT killer — blocks main thread during every API call
- Strategy: Replace all 4 functions with fetch() equivalents. Update callers if needed.
moment (~67KB)
- Used in: Date formatting throughout the app
- Replace with:
Intl.DateTimeFormat or date-fns (tree-shakeable)
- Strategy: Find all
moment() usages, replace with native or lightweight alternative
lodash (~72KB full)
- Replace with: Native JS equivalents or
lodash-es for tree shaking
- Strategy: Identify which lodash functions are used, replace with native
core-js + regenerator-runtime
- Purpose: Polyfills for IE11
- Replace with: Nothing — modern browsers don't need them
- Strategy: Remove from webpack entry array after updating Babel targets
Pitfalls
| Pitfall | Symptom | Fix |
|---|
| jQuery removal breaks $.ajax callers | Runtime errors in components using fetchers | Replace ALL 4 fetcher functions before removing jQuery |
| FFmpeg removal breaks PausableMovie | GIF videos don't play | Replace with <img> for GIFs or pre-convert to video |
| moment removal breaks date display | Dates show as [object Object] | Replace all moment() calls |
| Removing deps without updating imports | Build errors | grep for all import statements first |
VRT Risks
| Change | Visual Impact | Mitigation |
|---|
| jQuery → fetch | None if async behavior preserved | Test all data-loading components |
| FFmpeg removal | GIF playback may differ | Ensure GIFs still display (as <img> or <video>) |
| ImageMagick removal | Post creation image preview may break | Only affects post creation flow, not display |
| moment removal | Date format may change slightly | Match exact format strings |
Project-Specific Notes
fetchers.ts exports: fetchBinary, fetchJSON, sendFile, sendJSON — all use jQuery
async: false in fetchBinary and fetchJSON is the biggest single TBT issue
- webpack ProvidePlugin injects jQuery globally — must also remove that
jquery-binarytransport is in webpack entry — remove from entry array
- sendFile and sendJSON also use jQuery but don't use
async: false