perf(audit): emojibase lazy-split, SW precache, Prism subset, lazy images

- emojibase (~965 KB) is now fully lazy: plugins/emoji.ts loads compact data +
  shortcode maps via a memoized dynamic import (rejections reset the memo so a
  mid-deploy chunk 404 can retry); reaction labels degrade to the raw glyph
  until loaded. Consumers get FRESH array references on load (the module arrays
  populate in place — same-ref state updates would skip re-render and leave
  emoji search empty; reviewer-caught). Verified out of the eager graph.
- Service worker precaches hashed assets (workbox precacheAndRoute, 82 entries
  ~10.8 MB incl. the crypto wasm): repeat visits stop re-downloading the app.
  index.html is NOT precached — navigations stay network-first so deploys are
  picked up immediately; the media-auth fetch handler is untouched.
- ReactPrism: curated 21-language set — chunk 574 KB → 71 KB.
- Timeline inline images get loading="lazy".
- Removed dead dompurify (+types); sanitize-html is the real sanitizer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 00:19:16 -04:00
parent 664dcd4cd8
commit 96f7187031
11 changed files with 268 additions and 408 deletions
+13 -1
View File
@@ -261,7 +261,19 @@ export default defineConfig({
injectRegister: false,
manifest: false,
injectManifest: {
injectionPoint: undefined,
// PRECACHE (P5): emit `self.__WB_MANIFEST` into src/sw.ts so it can
// precacheAndRoute the hashed build assets. index.html is deliberately
// EXCLUDED from the manifest (globs only `assets/**`) so navigations
// stay network-first and a new deploy is picked up immediately — see
// the deploy-safety invariants documented in src/sw.ts.
injectionPoint: 'self.__WB_MANIFEST',
globPatterns: ['assets/**/*.{js,css,wasm}'],
// Assets are content-hashed, so the filename is the cache key — don't
// append a revision cache-busting param.
dontCacheBustURLsMatching: /assets\//,
// Raised above the 2 MB default so the ~5.5 MB matrix-sdk crypto wasm
// (hash-busted and hot on every session) is precached deliberately.
maximumFileSizeToCacheInBytes: 6 * 1024 * 1024,
// codeSplitting: false is not yet supported by vite-plugin-pwa 1.3.0;
// the inlineDynamicImports deprecation warning from Vite is from pwa internal build
},