supermemory icon indicating copy to clipboard operation
supermemory copied to clipboard

Fix excessive icon refetch made by importing bookmarks

Open fyzanshaik opened this issue 2 months ago โ€ข 6 comments

Twitter bookmark import was causing excessive icon refetching, making too many network requests during progress updates. If 1000 bookmakrs processed 1000 http requests are sent to fetch icon. Screenshot From 2025-10-19 06-25-59

Solution: Changed Twitter import button to use CSS background-image instead of <img> elements to load the icon once and cache it.

Changes:

  • Updated createTwitterImportButton() in ui-components.ts to use CSS background-image
  • Added cleanup code in updateTwitterImportUI() to handle old <img> elements
  • Icon now loads once via browser.runtime.getURL("/icon-16.png") and stays cached

Result:

  • Stops repeated icon requests during bookmark import updates
  • Better performance, fewer API calls
  • Same visual appearance, more efficient

Note: Same <img> issue exists in ChatGPT, Claude, T3, and toast notifications. Should create a utility function to fix this pattern across all platforms.

fyzanshaik avatar Oct 19 '25 01:10 fyzanshaik

How to use the Graphite Merge Queue

Add the label Main to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

graphite-app[bot] avatar Oct 19 '25 01:10 graphite-app[bot]

@fyzanshaik i have tested in prod i don't see this issue at all both in browser network tab and extension network tab

FYI: the requests are going to just extension, not to any server. image

MaheshtheDev avatar Oct 19 '25 02:10 MaheshtheDev

@MaheshtheDev I verified it once again, and yes the requests are happening to the extension itself. I guess its not a big deal

https://github.com/user-attachments/assets/242cbf44-6657-4efa-a4eb-51e6c3e1ca2a

fyzanshaik avatar Oct 19 '25 13:10 fyzanshaik

Code Review - PR #496: Fix Excessive Icon Refetch During Bookmark Import

Summary

This PR optimizes the Twitter bookmark import feature by eliminating excessive icon refetching. Instead of using <img> elements that trigger network requests on every UI update, it uses CSS background-image which loads the icon once and caches it.

โœ… Strengths

  • Performance Fix: Reduces 1000 HTTP requests to 1 when importing 1000 bookmarks
  • Root Cause Analysis: Correctly identifies the problem (repeated innerHTML assignments creating new img elements)
  • Backward Compatibility: Includes cleanup code to handle existing old <img> elements
  • Documentation: Well-documented PR description with clear before/after comparison
  • Identifies Future Work: Notes that the same pattern exists in other components

๐Ÿ“ Code Quality

Positives

  • Clean separation of concerns (icon setup vs text updates)
  • Proper DOM element reuse via #sm-import-text ID
  • Good inline styles organization

Suggestions for Improvement

1. Magic Numbers & Hardcoded Values

// Current
button.style.backgroundSize = "20px 20px"
button.style.paddingLeft = "28px"

// Suggest: Add constants at top of file
const ICON_SIZE = 20
const ICON_PADDING = 28 // ICON_SIZE + 8px gap

2. Font Size Inconsistency

// ui-components.ts uses 12px
textSpan.style.cssText = "font-weight: 500; font-size: 12px;"

// twitter.ts uses 14px
textSpan.style.cssText = "font-weight: 500; font-size: 14px;"

Question: Is this intentional? Should they be consistent?

3. Potential Memory Leak The existingImg.remove() handles backward compat, but consider:

  • Will old event listeners be cleaned up?
  • Could this cause issues if called multiple times?

4. DRY Principle Violation The icon setup code is duplicated between:

  • Initial button creation (createTwitterImportButton)
  • Cleanup/migration code (updateTwitterImportUI)

Recommendation: Extract to a shared function:

function applyIconBackground(element: HTMLElement, iconUrl: string) {
  element.style.backgroundImage = `url("${iconUrl}")`
  element.style.backgroundRepeat = "no-repeat"
  element.style.backgroundSize = "20px 20px"
  element.style.backgroundPosition = "left center"
  element.style.paddingLeft = "28px"
}

๐Ÿ”ง Technical Considerations

1. Browser Compatibility

  • CSS background-image approach is well-supported
  • No concerns for modern browsers

2. Accessibility

  • โœ… Proper alt text was preserved (though now in CSS)
  • โš ๏ธ Consider: Should there be an aria-label since the icon is now decorative in CSS?

3. Extension-Specific Concerns

  • browser.runtime.getURL() is correct for extension resources
  • Icon will be cached by browser automatically with this approach

๐Ÿงช Testing Recommendations

  • [ ] Test importing 1000+ bookmarks (verify performance improvement)
  • [ ] Test upgrading from old version (verify img cleanup works)
  • [ ] Test rapid UI updates during import
  • [ ] Verify visual appearance matches original
  • [ ] Test in different browsers (Chrome, Firefox, Edge)
  • [ ] Monitor network tab to confirm single icon request

๐ŸŽฏ Follow-up Items

As noted in the PR description:

  1. Apply same fix to ChatGPT button
  2. Apply same fix to Claude button
  3. Apply same fix to T3 button
  4. Apply same fix to toast notifications
  5. Create shared utility: createButtonWithCachedIcon() to prevent future occurrences

Suggestion: Create a tracking issue for these follow-ups to ensure they are addressed.

๐Ÿ” Security

  • No security concerns
  • Using proper extension API for resource URLs

โœ”๏ธ Verdict

Approve with minor suggestions - This is a solid performance optimization that addresses a real problem. The code works but could benefit from:

  1. Extracting magic numbers to constants
  2. Creating a shared utility function for the icon pattern
  3. Addressing the font-size inconsistency
  4. Adding aria-label for accessibility

The PR can be merged as-is, but I strongly recommend creating follow-up issues/PRs for:

  • Applying the same fix to other components mentioned
  • Creating the shared utility function
  • Adding constants for magic numbers

Great catch on the performance issue!


Review generated by Claude Code

claude[bot] avatar Oct 19 '25 23:10 claude[bot]

Code Review: Fix Excessive Icon Refetch

Summary

This PR fixes a real performance issue where importing 1000 bookmarks triggered 1000 HTTP requests for the same icon. The solution replaces img tags with CSS background-image to leverage browser caching. This is a solid performance fix with good execution.


Positive Aspects

  1. Correctly identifies the problem - Progress updates were causing repeated DOM manipulation and image reloads
  2. Effective solution - CSS background-image loads once and stays cached
  3. Backward compatibility - Handles cleanup of old img elements gracefully
  4. Maintains visual consistency - Same appearance, better performance
  5. Documents the issue - Notes that similar patterns exist in other platforms

Code Quality Analysis

1. Excellent: Separation of concerns

Location: apps/browser-extension/utils/ui-components.ts:187-200

Good: Icon loaded once via CSS, text in separate span for easy updates. Browser caches the background-image properly.

2. Smart: Backward compatibility handling

Location: apps/browser-extension/entrypoints/content/twitter.ts:123-133

Handles migration from old img approach gracefully. Ensures consistent behavior across updates with no breaking changes.


Issues and Concerns

1. Potential race condition (Low severity)

Location: apps/browser-extension/entrypoints/content/twitter.ts:160-165

Issue: If another import starts within the 3-second window after completion, the setTimeout could fire and reset the button to "Import Bookmarks" while an import is in progress.

Recommendation: Store timeout ID and clear it when new import starts.

2. Magic numbers and inconsistent styling (Minor)

Issues:

  • fontSize: "14px" in twitter.ts:145 but "12px" in ui-components.ts:197 - should be consistent
  • Hardcoded color #059669 in twitter.ts:156 - should be a constant
  • Multiple inline styles instead of CSS classes

Recommendation: Create constants for reusability.

3. Inconsistent icon size handling

Icon size (20px) is duplicated in two places. Should be a constant to avoid drift.


Performance Analysis

Before:

  • 1000 bookmarks = 1000+ HTTP requests for the same icon
  • Each innerHTML update creates new img element โ†’ browser fetches icon again

After:

  • 1 HTTP request for icon (CSS background-image)
  • Text updates only modify DOM text node

Performance gain: โญโญโญโญโญ Excellent - ~99% reduction in icon-related network time


Testing Recommendations

  1. Performance testing - Verify only ONE request to icon-16.png with 100+ bookmarks
  2. Visual regression - Compare button appearance, test success state
  3. Edge cases - Test back-to-back imports, cache disabled, slow network
  4. Backward compatibility - Test upgrade mid-import

Suggested Changes

  1. HIGH PRIORITY: Add timeout cleanup to prevent race condition
  2. MEDIUM PRIORITY: Extract magic numbers to constants, make font-size consistent
  3. FUTURE WORK: Apply fix to ChatGPT, Claude, T3, and toast notifications

Security Analysis

Status: No security concerns identified

  • Uses browser.runtime.getURL() - trusted source
  • No user input in CSS values
  • No XSS vectors

Code Quality: 8.5/10

Pros: Solves real performance problem, clean implementation, good backward compatibility

Cons: Minor race condition possible, some magic numbers, font size inconsistency


Approval Status: Approve with minor suggestions

This is a solid performance fix. The core fix is excellent and should be merged soon. Suggested improvements can be follow-up PRs if needed.


Additional Note

Great catch on identifying this pattern in other platforms! Consider creating a utility function for reusable icon button creation.

claude[bot] avatar Oct 23 '25 05:10 claude[bot]

Cartoon gif. Batman from Batman: The Animated Series stands in the corner of a cave and stares down at us. He gives us a thumbs up, never changing expressions during it. (Added via Giphy)

graphite-app[bot] avatar Oct 28 '25 00:10 graphite-app[bot]