How We Slashed OpenSumi IDE Lag: Real-World React Rendering Optimizations

This article details practical performance optimizations applied to the OpenSumi IDE—using React memoization, component splitting, menu caching, tree view prop pruning, and icon batch insertion—to dramatically reduce unnecessary re‑renders and improve UI responsiveness.

Alibaba Terminal Technology
Alibaba Terminal Technology
Alibaba Terminal Technology
How We Slashed OpenSumi IDE Lag: Real-World React Rendering Optimizations

Performance optimization is a classic topic; while many advise against premature optimization, for an IDE whose performance affects almost everything, any delay is unacceptable. After a user survey revealed frequent UI stalls—slow opening, sluggish completion, and general lag—we began systematic improvements.

Re‑render

OpenSumi renders its view layer with React, so the usual goal is to reduce unnecessary re‑renders. Dan Abramov’s "Before You memo()" article shows that splitting components and memoizing immutable parts can avoid costly updates. However, OpenSumi’s heavy use of MobX makes most state effectively global, limiting the impact of simple memoization.

We therefore rely on React.memo and useMemo after ensuring that state is appropriately scoped.

React DevTools helps locate obvious problems; enabling "Highlight updates when components render" quickly reveals components that render when they shouldn’t.

Search Panel

The search panel contains only four inputs and a few buttons, yet any global state change triggers a full re‑render. By extracting each input and checkbox into independent components (e.g., SearchInput, SearchExclude, SearchInclude, SearchResult) and wrapping them with React.memo, we prevent unnecessary updates.

const SearchView = () => {
  const searchService = useInjectable<ISearchService>(SearchService);
  return (
    <div>
      <Input value={searchService.uiState.searchKeyWord} />
      <Checkbox checked={searchService.uiState.checkbox} />
      <Input />
      <Input />
    </div>
  );
}
const SearchView = () => {
  const searchService = useInjectable<ISearchService>(SearchService);
  return (
    <div>
      <SearchInclude includes={searchService.includes} />
    </div>
  );
}
const SearchInclude = React.memo((props) => (<Input value={props.includes} />));

Inconspicuous Menus

Menus appear trivial but are abundant, especially when OpenSumi supports VS Code extensions that inject custom menu items via ContributionPoint. Each menu instance recreates its internal menuitem objects on every render, leading to hundreds of redundant creations.

Adding a simple cache to the menu factory eliminates the repeated construction:

private getInlineMenu(viewItemValue: string) {
  if (this.cachedMenu.has(viewItemValue)) {
    return this.cachedMenu.get(viewItemValue)!;
  }
  // create new menu
  this.cachedMenu.set(viewItemValue);
}

TreeView

TreeView components (file tree, symbol tree, etc.) are built on RecycleTree. Unnecessary width props cause the entire tree to re‑render during panel resizing. Removing the superfluous width prop fixes the issue.

// before
<RecycleTree ...otherProps width={width} height={height} />
// after
<RecycleTree ...otherProps height={height} />

Icon Handling

Plugins like GitLens register hundreds of icons for committers. Each icon is turned into a CSS class and injected into a <style> tag. When this happens thousands of times, the DOM repaint becomes a major bottleneck. Batch‑inserting the generated CSS rules resolves the slowdown.

`.${className} {background: url("${iconUrl}") no-repeat 50% 50%; background-size: contain;}`;

Restraining Resize Events

All panels listen to a global ResizeObserver. Even when a panel is hidden (display:none) or shown (display:block), the observer fires, causing unnecessary renders. By caching the previous size with useRef and only broadcasting when dimensions actually change, we cut the extra render.

Conclusion

The article showcases several obvious performance fixes—memoizing components, caching menus, pruning props, batching icon CSS, and limiting resize events. Most bottlenecks stem from simple oversights rather than deep architectural problems, demonstrating that systematic, incremental tweaks can dramatically improve IDE responsiveness.

Feel free to star and play with OpenSumi (nickname KAITIAN): https://github.com/opensumi/core
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

optimizationReactIDEOpenSumi
Alibaba Terminal Technology
Written by

Alibaba Terminal Technology

Official public account of Alibaba Terminal

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.