Skip to content

perf: lazy load heavy first-screen dependencies#5947

Merged
boojack merged 3 commits into
mainfrom
perf/lazy-first-screen-deps
May 12, 2026
Merged

perf: lazy load heavy first-screen dependencies#5947
boojack merged 3 commits into
mainfrom
perf/lazy-first-screen-deps

Conversation

@boojack

@boojack boojack commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Lazy-load Home, map UI, profile map, and Mermaid so auth/signup first render does not preload memo/map/diagram dependencies.
  • Move Leaflet and KaTeX CSS out of the app entry and into feature-loaded paths.
  • Replace editor-facing Leaflet LatLng state with plain MapPoint coordinates to keep parent chunks Leaflet-free.

Test Plan

  • cd web && pnpm lint && pnpm build
  • cd web && pnpm test (14 files, 75 tests)
  • Production preview browser check on /auth/signup: no Mermaid/Leaflet/KaTeX asset tags
  • rg -n "mermaid|leaflet|katex" web/dist/index.html returns no matches

Note: Live authenticated memo/map smoke tests were not run because the preview did not have a backend session or seeded memo data.

@boojack boojack requested a review from a team as a code owner May 12, 2026 11:42
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR optimizes first-screen load performance for the /auth/signup route by removing eager imports of heavy optional dependencies (Mermaid, Leaflet, KaTeX). The changes introduce a MapPoint coordinate type, lazy-load map and profile components behind Suspense boundaries, convert Mermaid and KaTeX to dynamic/deferred loading, and adjust build configuration to prevent these features from entering the auth entry chunk.

Changes

First-Screen Performance Optimization

Layer / File(s) Summary
MapPoint coordinate abstraction
web/src/components/map/types.ts
New MapPoint interface replaces Leaflet LatLng as the app's internal coordinate representation.
Editor location state and MapPoint adoption
web/src/components/MemoEditor/types/insert-menu.ts, web/src/components/MemoEditor/hooks/useLocation.ts, web/src/components/MemoEditor/Toolbar/InsertMenu.tsx
Editor hooks, state types, and toolbar components updated to use plain MapPoint coordinate objects instead of constructing Leaflet LatLng instances.
LocationPicker modernization with coordinate conversion
web/src/components/map/LocationPicker.tsx, web/src/components/map/index.ts
LocationPicker introduces toLatLng/fromLatLng helpers; now accepts and emits MapPoint for position data while maintaining internal Leaflet usage. Control components updated to accept MapPoint. Barrel exports narrowed to prevent unintended eager imports.
LazyLocationPicker Suspense wrapper
web/src/components/map/LazyLocationPicker.tsx
New component lazy-loads LocationPicker via React.lazy with Suspense boundary and styled placeholder, enabling map UI to load only when opened.
Location dialog and display view lazy rendering
web/src/components/MemoMetadata/Location/LocationDialog.tsx, web/src/components/MemoMetadata/Location/LocationDisplayView.tsx
Dialog and view components conditionally render LazyLocationPicker only when their UI is active, replacing eager imports; callbacks updated to use MapPoint.
UserProfile map lazy-loading and Leaflet CSS localization
web/src/pages/UserProfile.tsx, web/src/components/UserMemoMap/UserMemoMap.tsx
UserProfile lazy-loads UserMemoMap with Suspense fallback; Leaflet stylesheet imported into UserMemoMap so CSS loads only when map renders.
Dynamic Mermaid import and deferred KaTeX styling
web/src/components/MemoContent/MermaidBlock.tsx, web/src/components/MemoContent/MemoMarkdownRenderer.tsx
MermaidBlock converts to dynamic import("mermaid") at render effect time with async rendering and cancellation guards; MemoMarkdownRenderer imports KaTeX CSS where it is used rather than globally.
Entry point cleanup and routing lazy-loading
web/src/main.tsx, web/src/router/index.tsx, web/vite.config.mts
Leaflet and KaTeX CSS removed from main.tsx. Router converts Home page to lazy-loaded via lazyWithReload. Vite config narrows leaflet-vendor chunk rule to isolate Leaflet separately from React-Leaflet.
Implementation plan and design specification
docs/superpowers/plans/2026-05-12-first-screen-lazy-heavy-deps.md, docs/superpowers/specs/2026-05-12-first-screen-lazy-heavy-deps-design.md
Task-by-task plan with verification steps and checklist; design spec covering architecture, data flow, error handling, and testing expectations.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main objective: lazy loading heavy first-screen dependencies to optimize performance.
Description check ✅ Passed The description is directly related to the changeset, explaining the lazy-loading approach, CSS relocation, and coordinate type replacement.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/superpowers/plans/2026-05-12-first-screen-lazy-heavy-deps.md (1)

714-729: Please complete and attach results for the live smoke checks before merge.

Static build verification is good, but these lazy boundaries still need runtime validation in an authenticated/seeded environment (Mermaid render, KaTeX styling, location picker/popover, profile map tab).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-05-12-first-screen-lazy-heavy-deps.md` around
lines 714 - 729, Finish the live smoke tests described in "Step 5: Smoke test
feature lazy loading" by running the app in an authenticated, seeded environment
and verifying each item: confirm Mermaid diagrams lazy-load and render when a
memo with a Mermaid code block appears, confirm KaTeX styling loads for
inline/block math, verify the location picker loads Leaflet assets and remains
interactive, verify memo location popovers load Leaflet and show pinned maps,
and verify `/u/:username?view=map` loads the profile map with marker clustering;
capture screenshots, short reproduction steps, and any console/network logs
showing the lazy chunk requests and attach those results to this PR before
merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/src/components/map/LocationPicker.tsx`:
- Around line 214-217: The derived LatLng objects created by calling
toLatLng(...) each render cause the initialPosition effect to think coordinates
changed and call map.setView; in LocationPicker replace the direct calls to
toLatLng for mapCenter and markerPosition with memoized values (useMemo) that
only recompute when the underlying numeric coordinates change (e.g., depend on
latlng?.lat and latlng?.lng or the DEFAULT_CENTER coords), and use that memoized
mapCenter in the initialPosition effect so map.setView is only invoked when
coordinates truly change.

In `@web/src/components/MemoContent/MermaidBlock.tsx`:
- Around line 41-43: The effect in MermaidBlock's useEffect exits early when
codeContent is falsy and thus leaves previously rendered SVG/error visible;
update the effect to explicitly reset the component state when codeContent is
empty by clearing any rendered output and errors (e.g., call the state setters
used for the rendered SVG and error inside the early-return branch), ensuring
the hook (useEffect in MermaidBlock.tsx) resets the diagram state whenever
codeContent becomes empty.

---

Nitpick comments:
In `@docs/superpowers/plans/2026-05-12-first-screen-lazy-heavy-deps.md`:
- Around line 714-729: Finish the live smoke tests described in "Step 5: Smoke
test feature lazy loading" by running the app in an authenticated, seeded
environment and verifying each item: confirm Mermaid diagrams lazy-load and
render when a memo with a Mermaid code block appears, confirm KaTeX styling
loads for inline/block math, verify the location picker loads Leaflet assets and
remains interactive, verify memo location popovers load Leaflet and show pinned
maps, and verify `/u/:username?view=map` loads the profile map with marker
clustering; capture screenshots, short reproduction steps, and any
console/network logs showing the lazy chunk requests and attach those results to
this PR before merging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 96ddb5b9-019d-44d6-b90f-ec198dedee44

📥 Commits

Reviewing files that changed from the base of the PR and between 7f1f53f and ead1f06.

📒 Files selected for processing (18)
  • docs/superpowers/plans/2026-05-12-first-screen-lazy-heavy-deps.md
  • docs/superpowers/specs/2026-05-12-first-screen-lazy-heavy-deps-design.md
  • web/src/components/MemoContent/MemoMarkdownRenderer.tsx
  • web/src/components/MemoContent/MermaidBlock.tsx
  • web/src/components/MemoEditor/Toolbar/InsertMenu.tsx
  • web/src/components/MemoEditor/hooks/useLocation.ts
  • web/src/components/MemoEditor/types/insert-menu.ts
  • web/src/components/MemoMetadata/Location/LocationDialog.tsx
  • web/src/components/MemoMetadata/Location/LocationDisplayView.tsx
  • web/src/components/UserMemoMap/UserMemoMap.tsx
  • web/src/components/map/LazyLocationPicker.tsx
  • web/src/components/map/LocationPicker.tsx
  • web/src/components/map/index.ts
  • web/src/components/map/types.ts
  • web/src/main.tsx
  • web/src/pages/UserProfile.tsx
  • web/src/router/index.tsx
  • web/vite.config.mts
💤 Files with no reviewable changes (2)
  • web/src/components/map/index.ts
  • web/src/main.tsx

Comment thread web/src/components/map/LocationPicker.tsx Outdated
Comment thread web/src/components/MemoContent/MermaidBlock.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
web/tests/location-picker.test.tsx (1)

6-12: ⚡ Quick win

Reset shared mocks between tests to avoid call-count leakage.

These spies are module-scoped and will retain call history across future tests in this file unless explicitly reset.

Suggested change
 import { render } from "@testing-library/react";
 import type { ReactNode } from "react";
-import { describe, expect, it, vi } from "vitest";
+import { beforeEach, describe, expect, it, vi } from "vitest";
 import LocationPicker from "@/components/map/LocationPicker";
@@
 const eventMap = { setView, locate };
 const controlMap = { zoomIn, zoomOut };
+
+beforeEach(() => {
+  vi.clearAllMocks();
+});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/tests/location-picker.test.tsx` around lines 6 - 12, Module-scoped spies
(setView, locate, zoomIn, zoomOut) leak call counts across tests; fix by
resetting or recreating them between tests—either move creation of
eventMap/controlMap and their vi.fn() mocks into a beforeEach so each test gets
fresh mocks, or add a beforeEach/afterEach that calls vi.clearAllMocks() or
vi.resetAllMocks() to clear call history for setView, locate, zoomIn, zoomOut
(and any other module-scoped mocks) before each test run.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web/tests/location-picker.test.tsx`:
- Around line 6-12: Module-scoped spies (setView, locate, zoomIn, zoomOut) leak
call counts across tests; fix by resetting or recreating them between
tests—either move creation of eventMap/controlMap and their vi.fn() mocks into a
beforeEach so each test gets fresh mocks, or add a beforeEach/afterEach that
calls vi.clearAllMocks() or vi.resetAllMocks() to clear call history for
setView, locate, zoomIn, zoomOut (and any other module-scoped mocks) before each
test run.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d7bd1d21-7283-4f2a-874d-15471bbc23fa

📥 Commits

Reviewing files that changed from the base of the PR and between ead1f06 and 54eb553.

📒 Files selected for processing (4)
  • web/src/components/MemoContent/MermaidBlock.tsx
  • web/src/components/map/LocationPicker.tsx
  • web/tests/location-picker.test.tsx
  • web/tests/mermaid-block.test.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • web/src/components/MemoContent/MermaidBlock.tsx
  • web/src/components/map/LocationPicker.tsx

@boojack boojack merged commit a6024ee into main May 12, 2026
3 checks passed
@boojack boojack deleted the perf/lazy-first-screen-deps branch May 12, 2026 12:11
dgalanberasaluce pushed a commit to dgalanberasaluce/infra-personal that referenced this pull request Jun 13, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [neosmemo/memos](https://github.com/usememos/memos) | minor | `0.28.0` → `0.29.0` |

---

### Release Notes

<details>
<summary>usememos/memos (neosmemo/memos)</summary>

### [`v0.29.0`](https://github.com/usememos/memos/blob/HEAD/CHANGELOG.md#0290-2026-05-27)

[Compare Source](usememos/memos@v0.28.0...v0.29.0)

##### Features

- **about:** add about page with bird sprites ([411ba7b](usememos/memos@411ba7b))
- **activity-calendar:** aggregate by ViewContext.timeBasis ([8daef1d](usememos/memos@8daef1d))
- add \<Placeholder> component with ASCII bird states ([#&#8203;5949](usememos/memos#5949)) ([8c16ffa](usememos/memos@8c16ffa))
- add configurable `--log-level` flag ([#&#8203;5934](usememos/memos#5934)) ([f1e2a06](usememos/memos@f1e2a06))
- add dedicated shortcuts page ([#&#8203;5942](usememos/memos#5942)) ([1df6479](usememos/memos@1df6479))
- add link metadata endpoints ([9c5c604](usememos/memos@9c5c604))
- **frontend:** add pixel bird tilemaps ([cf55f11](usememos/memos@cf55f11))
- **memo:** add task list quick actions ([#&#8203;5983](usememos/memos#5983)) ([648b3bd](usememos/memos@648b3bd))
- **memo:** create memos on the selected calendar date ([#&#8203;5925](usememos/memos#5925)) ([ef55013](usememos/memos@ef55013))
- **notification:** add smtp email settings ([cd4f28a](usememos/memos@cd4f28a))
- **placeholder:** add woodpecker tilemap ([638e4f3](usememos/memos@638e4f3))
- render link metadata cards ([0bc5669](usememos/memos@0bc5669))
- **stats:** admin instance resource statistics ([ea0625d](usememos/memos@ea0625d))
- **stats:** support filtered all-user stats ([88ac3ec](usememos/memos@88ac3ec))
- **transcription:** explicit STT settings with provider, model, prompt ([#&#8203;5926](usememos/memos#5926)) ([238f27d](usememos/memos@238f27d))

##### Bug Fixes

- avoid update event on memo create attachments ([#&#8203;5961](usememos/memos#5961)) ([3c3382a](usememos/memos@3c3382a))
- delete user cleanup ([#&#8203;5981](usememos/memos#5981)) ([e53b7d9](usememos/memos@e53b7d9))
- **editor:** wrap selected text when pasting URL ([e0bb3a2](usememos/memos@e0bb3a2))
- **fileserver:** preserve HDR image metadata in thumbnails ([c724232](usememos/memos@c724232))
- **frontend:** correct static cache headers ([084f40b](usememos/memos@084f40b))
- **frontend:** use correct url path for memos in sitemap.xml ([#&#8203;5921](usememos/memos#5921)) ([603781f](usememos/memos@603781f))
- **httpgetter:** prevent DNS rebinding in link metadata fetch ([078488c](usememos/memos@078488c))
- **markdown:** align list items with checkboxes ([e008b1a](usememos/memos@e008b1a))
- **memo:** enforce parent visibility for comments ([4a1e401](usememos/memos@4a1e401))
- **s3presign:** preserve motion media payload ([7f1f53f](usememos/memos@7f1f53f))
- **security:** enforce attachment ownership on memo updates ([35bf761](usememos/memos@35bf761))
- **sse:** stream initial response and refresh tokens ([21303e8](usememos/memos@21303e8))
- **user:** omit internal settings from list responses ([#&#8203;5917](usememos/memos#5917)) ([1df3fe7](usememos/memos@1df3fe7))
- **web:** sync avatar changes immediately after profile update ([#&#8203;5903](usememos/memos#5903)) ([328396a](usememos/memos@328396a))

##### Performance Improvements

- lazy load heavy first-screen dependencies ([#&#8203;5947](usememos/memos#5947)) ([a6024ee](usememos/memos@a6024ee))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My43My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNzMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->

Reviewed-on: https://forgejo.internal/forgejo_admin/infra-personal/pulls/96
Co-authored-by: Renovate Bot <renovatebot@forgejo.internal>
Co-committed-by: Renovate Bot <renovatebot@forgejo.internal>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant