fix(link-preview): use static api import so previews load under BASE_URL#3541
Conversation
fetchLinkPreview() did `await import('../services/api')`. Vite computed that
lazy chunk's preload URL without the runtime BASE_URL prefix (/assets/… instead
of /meshmonitor/assets/…), so it 404'd and threw "Unable to preload CSS" on any
page where the chunk wasn't already loaded. The error was caught and returned
null, so no preview card rendered — most visibly on the MeshCore channel, room
server, and DM views (the Meshtastic/dashboard pages had already loaded the
chunk's CSS, masking it there).
The api service is already in the main bundle and statically imported across the
app; it does not import this module, so the "avoid circular dependencies"
justification doesn't hold. Import it statically to drop the fragile dynamic
import entirely.
Adds linkRenderer tests (fetchLinkPreview delegate + null-on-error, extractUrls).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SVGxkuD4Fwa2JGVim8ZeVj
|
Claude finished @Yeraze's task —— View job PR Review: fix(link-preview): use static api importTasks:
SummaryThis is a clean, well-targeted fix. The root cause diagnosis is accurate and the solution is correct. Here's my detailed review: Code Quality ✅
The change is minimal and correct — replacing One minor point: the const metadata = await api.fetchLinkPreview(url);
return metadata;This could be simplified to Test Coverage ✅
The mock structure correctly uses One gap: there's no test for Performance ✅The fix is a strict improvement: eliminating the dynamic import means one fewer lazy chunk, one fewer potential preload race, and slightly faster first-render of any component that calls Security ✅No security concerns. The URL passed to One observation (pre-existing, not introduced by this PR): Maintainer Note EndorsedThe PR description correctly flags that other lazy chunks (emoji picker, VerdictApprove — the fix is correct, minimal, and well-tested. No blocking issues. |
Summary
Link previews silently failed to render on the MeshCore channel, room server, and DM displays (and on the first messages page visited in a session). Root cause:
fetchLinkPreview()used a dynamicimport('../services/api'), and Vite computed that lazy chunk's preload URL without the runtimeBASE_URLprefix — requesting/assets/…instead of/meshmonitor/assets/…. That 404'd, Vite's preload helper threwUnable to preload CSS, thecatchreturnednull, and no preview card rendered.Diagnosed from the live instance's browser console:
The component, setting (
linkPreviewsEnabled), URL extraction, CSS, and the/api/link-previewendpoint all worked — the endpoint returns full metadata for the exact message URLs. It looked MeshCore-specific only because the Meshtastic/dashboard pages had already loaded that chunk's CSS (the map usesGeoJsonOverlay), masking the broken preload there.Changes
src/utils/linkRenderer.ts(x): import theapiservice statically instead of viaawait import('../services/api').apiis already in the main bundle and statically imported across the app, and it does not importlinkRenderer, so the original "avoid circular dependencies" justification doesn't hold. Removing the dynamic import eliminates the fragile, base-path-sensitive preload entirely.src/utils/linkRenderer.test.ts(the file had no tests):fetchLinkPreviewdelegates to the api service and resolvesnull(no throw) on failure;extractUrlscovers query strings, barewww., and the no-URL case.Issues Resolved
None filed — reported directly ("link previews not showing on MeshCore").
Note for maintainers
The underlying cause is that dynamic-import (lazy chunk) preload URLs don't pick up the runtime
BASE_URL, while the entry bundle and API calls do. This fix removes the one dynamic import in the link-preview path, but other lazy chunks (e.g. emoji picker,GeoJsonOverlay, embed) load via the same mechanism and could 404 on first use under a non-rootBASE_URL. Worth a separate look at the Vitebase/ runtime-base handling for code-split chunks.Documentation Updates
Testing
linkRenderer.test.ts(5 tests) + existingLinkPreview.test.tsxpassBASE_URL(e.g./meshmonitor), open a MeshCore channel/room/DM containing a URL and confirm the preview card renders (no/assets/…404 in the console)🤖 Generated with Claude Code