How Alibaba’s IDE Co‑Development Revamped Tree Components for Lightning‑Fast Performance

This article details the evolution of Alibaba’s IDE co‑development project, focusing on the design, data structures, event model, rendering, and performance optimizations of a high‑performance Tree component used for file navigation and other hierarchical views within the KAITIAN framework.

Taobao Frontend Technology
Taobao Frontend Technology
Taobao Frontend Technology
How Alibaba’s IDE Co‑Development Revamped Tree Components for Lightning‑Fast Performance

IDE Co‑Development Deep Dive

In early 2019 the author joined Alibaba’s IDE co‑development project to build a public IDE core for the ecosystem. The Tree component, a core UI element for file, debug, and other views, was refactored twice; this article explains the latest high‑performance implementation in the KAITIAN framework.

What does a Tree component look like?

Typical Tree components consist of regular and collapsible nodes, with various decorations such as selection state and icons.

All examples below use a file‑tree as the reference.

Expected Data Structure

The basic data structure for a Tree is a flattened two‑dimensional array (FlattenedBranch) that stores each node’s position (index) and a unique identifier (node ID).

Event‑Driven Model

Parent‑child communication is handled through an event‑watcher interface, allowing the root to listen to any change in the tree.

export interface ITreeWatcher {
  // Listen to watchEvent such as node move, create, delete
  onWatchEvent(path: string, callback: IWatcherCallback): IWatchTerminator;
  // Listen to all events
  on(event: TreeNodeEvent, callback: any);
  // Notify parent will change
  notifyWillChangeParent(target: ITreeNodeOrCompositeTreeNode, prevParent: ICompositeTreeNode, newParent: ICompositeTreeNode);
  // Notify parent changed
  notifyDidChangeParent(target: ITreeNodeOrCompositeTreeNode, prevParent: ICompositeTreeNode, newParent: ICompositeTreeNode);
  // Notify node will be disposed
  notifyWillDispose(target: ITreeNodeOrCompositeTreeNode);
  // Notify node disposed
  notifyDidDispose(target: ITreeNodeOrCompositeTreeNode);
  // Notify node will process watch event (used in file tree)
  notifyWillProcessWatchEvent(target: ICompositeTreeNode, event: IWatcherEvent);
  // Notify node did process watch event
  notifyDidProcessWatchEvent(target: ICompositeTreeNode, event: IWatcherEvent);
  // Notify expansion state will change
  notifyWillChangeExpansionState(target: ICompositeTreeNode, nowExpanded: boolean);
  // Notify expansion state did change
  notifyDidChangeExpansionState(target: ICompositeTreeNode, nowExpanded: boolean);
  // Notify children will resolve
  notifyWillResolveChildren(target: ICompositeTreeNode, nowExpanded: boolean);
  // Notify children resolved
  notifyDidResolveChildren(target: ICompositeTreeNode, nowExpanded: boolean);
  // Notify path changed
  notifyDidChangePath(target: ITreeNodeOrCompositeTreeNode);
  // Notify metadata changed
  notifyDidChangeMetadata(target: ITreeNodeOrCompositeTreeNode, change: IMetadataChange);
  // Notify branch updated
  notifyDidUpdateBranch();
  // Dispose function
  dispose: IDisposable;
}

All nodes hold a reference to this watcher, so a single on call at the root can capture changes across the entire tree, enabling features such as snapshots and undo/redo.

Node Rendering Model

The Tree is essentially a long list; each node renders with indentation to appear hierarchical. Hardware acceleration can be triggered by using transform: translateY(0) in CSS.

For large trees (thousands of nodes) only a subset of nodes is rendered at any time, with pre‑rendered buffers before and after the visible range to improve scrolling.

When the scroll reaches a boundary, the start index is updated and React’s diff algorithm re‑uses DOM nodes, achieving node recycling.

Data Service Layer

Each collapsible node must be able to fetch its children, which is provided by a TreeService implementation.

File‑tree nodes are defined by extending CompositeTreeNode (for directories) and TreeNode (for files):

export class Directory extends CompositeTreeNode {
  constructor(
    tree: ITree,
    public readonly parent: CompositeTreeNode | undefined,
    public uri: URI = new URI(''),
    public name: string = '',
    public filestat: FileStat = { children: [], isDirectory: false, uri: '', lastModification: 0 },
    public tooltip: string,
  ) {
    super(tree, parent);
    if (!parent) {
      // Root node expands by default
      this.setExpanded();
    }
  }
}

export class File extends TreeNode {
  constructor(
    tree: ITree,
    public readonly parent: CompositeTreeNode | undefined,
    public uri: URI = new URI(''),
    public name: string = '',
    public filestat: FileStat = { children: [], isDirectory: false, uri: '', lastModification: 0 },
    public tooltip: string,
  ) {
    super(tree, parent);
  }
}

The service that resolves children and sorts nodes:

export class FileTreeService extends Tree {
  async resolveChildren(parent?: Directory) {
    // ... fetch child nodes logic
  }
  sortComparator(a: ITreeNodeOrCompositeTreeNode, b: ITreeNodeOrCompositeTreeNode) {
    // ... node sorting logic
  }
}

The model separates data from rendering, allowing pre‑processing before the view consumes it.

export class FileTreeModel extends TreeModel {
  constructor(@Optional() root: Directory) {
    super();
    // additional initialization if needed
  }
}

Rendering Function Example

const renderFileTree = () => {
  if (isReady) {
    return (
      <RecycleTree
        height={filterMode ? height - FILTER_AREA_HEIGHT : height}
        width={width}
        itemHeight={FILE_TREE_NODE_HEIGHT}
        onReady={handleTreeReady}
        model={fileTreeModelService.treeModel}
        filter={filter}
      >
        {(props: INodeRendererProps) => (
          <FileTreeNode
            item={props.item}
            itemType={props.itemType}
            decorationService={decorationService}
            labelService={labelService}
            dndService={fileTreeModelService.dndService}
            decorations={fileTreeModelService.decorations.getDecorations(props.item)}
            onClick={handleItemClicked}
            onTwistierClick={handleTwistierClick}
            onContextMenu={handlerContextMenu}
          />
        )}
      </RecycleTree>
    );
  }
};

Performance Comparison

New file tree vs. old file tree performance.

New file tree vs. VS Code file tree performance.

After the second refactor, the new implementation outperforms both the previous version and VS Code’s tree component.

Key reasons for the performance gap:

React’s virtual DOM diff provides advantages over direct DOM manipulation in large‑file scenarios.

Flattened, non‑recursive data model reduces traversal cost.

Rendering model defined in the parent allows on‑demand allocation without redundant checks in the core tree.

Beyond Performance

The redesigned Tree component also offers extensibility: developers can quickly create SearchTree, GitTree, TodoTree, etc., by defining a model, node data, and rendering logic. Data‑model separation enables pre‑loading data before the page renders, improving first‑paint times. Combined with dependency injection, multiple tree instances can be generated from a single token.

Conclusion

The current KAITIAN framework’s Tree component has only undergone the first phase (file‑tree) of refactoring. Ongoing optimizations will eventually replace all tree‑like views in the framework, providing a more reusable and high‑performance foundation for future scenarios.

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.

tree component
Taobao Frontend Technology
Written by

Taobao Frontend Technology

The frontend landscape is constantly evolving, with rapid innovations across familiar languages. Like us, your understanding of the frontend is continually refreshed. Join us on Taobao, a vibrant, all‑encompassing platform, to uncover limitless potential.

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.