npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

react-pprof

v1.3.2

Published

React component for visualizing pprof with WebGL

Downloads

4,165

Readme

react-pprof

A React component for visualizing pprof profiles using WebGL.

CI Lint

Features

  • 🚀 WebGL-accelerated rendering for smooth performance with large datasets
  • 🎨 Customizable theming with multiple color schemes
  • 🔍 Interactive zoom and pan with smooth animations
  • 📊 Stack trace visualization with complete call hierarchy
  • 🎯 Frame details panel showing children and parent relationships
  • 📱 Responsive design that works on all screen sizes
  • 🔧 TypeScript support with full type definitions
  • 🧪 Comprehensive testing with visual regression tests
  • High performance optimized for large profile datasets
  • 💻 Command Line Interface for generating static HTML flamegraphs

Installation

npm install react-pprof

Quick Start

import React, { useState, useEffect } from 'react'
import { FullFlameGraph, fetchProfile } from 'react-pprof'

function App() {
  const [profile, setProfile] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)

  useEffect(() => {
    fetchProfile('/path/to/profile.pprof')
      .then(setProfile)
      .catch(setError)
      .finally(() => setLoading(false))
  }, [])

  if (loading) return <div>Loading profile...</div>
  if (error) return <div>Error: {error.message}</div>
  if (!profile) return <div>No profile data</div>

  return (
    <FullFlameGraph
      profile={profile}
      height={600}
      showHottestFrames={true}
      showControls={true}
      showStackDetails={true}
    />
  )
}

Server-Side Embedding API

For programmatic generation of embeddable flamegraphs (e.g., for middleware or dynamic HTML generation), use the embedding API that supports rendering multiple graphs efficiently:

import { generateEmbeddableFlameGraph, getFlamegraphBundle } from 'react-pprof'
import fs from 'fs'

// Get the bundle once (it's cached internally)
const { bundle } = await getFlamegraphBundle()

// Generate embeddable flamegraphs for multiple profiles
const cpuProfile = fs.readFileSync('cpu-profile.pb')
const heapProfile = fs.readFileSync('heap-profile.pb')

const cpuGraph = await generateEmbeddableFlameGraph(cpuProfile, {
  title: 'CPU Profile',
  filename: 'cpu-profile.pb',
  primaryColor: '#ff4444',
  secondaryColor: '#ffcc66',
  height: 500
})

const heapGraph = await generateEmbeddableFlameGraph(heapProfile, {
  title: 'Heap Profile',
  filename: 'heap-profile.pb',
  primaryColor: '#ff4444',
  secondaryColor: '#ffcc66',
  height: 500
})

// Use in your HTML response
const fullPage = `
<!DOCTYPE html>
<html>
<head><title>Profiles</title></head>
<body>
  <h2>CPU Profile</h2>
  ${cpuGraph.html}

  <h2>Heap Profile</h2>
  ${heapGraph.html}

  <!-- Include bundle once -->
  <script>${bundle}</script>

  <!-- Render each graph -->
  <script>${cpuGraph.script}</script>
  <script>${heapGraph.script}</script>
</body>
</html>
`

API

getFlamegraphBundle()

Returns the reusable React-pprof bundle code (cached after first call). Include this once in your page before rendering any graphs.

Promise<{ bundle: string }>

generateEmbeddableFlameGraph(profileBuffer, options)

Generates embeddable HTML and JavaScript for a single flamegraph. Can be called multiple times for different graphs on the same page.

interface EmbeddableFlameGraphOptions {
  title?: string           // Display title (default: 'Profile')
  filename?: string        // Original filename (default: 'profile.pb')
  primaryColor?: string    // Primary color (default: '#ff4444')
  secondaryColor?: string  // Secondary color (default: '#ffcc66')
  height?: number         // Container height in pixels (default: 500)
}

interface EmbeddableFlameGraphResult {
  html: string    // HTML container div with unique ID
  script: string  // JavaScript code to render into the container
}

Key Features

  • Reusable bundle: The React-pprof bundle is loaded once and cached, improving performance when rendering multiple graphs
  • No global conflicts: Each graph uses unique IDs and local variables, so multiple graphs can coexist without conflicts
  • Self-contained: Generated HTML includes all necessary styling and structure
  • Efficient: Profile data is embedded efficiently and decoded on the client side

Command Line Interface (CLI)

This package includes a CLI utility to generate static HTML flamegraphs from pprof files without requiring a running server.

Installation

Install the CLI globally or use via npx:

# Install globally
npm install -g react-pprof

# Or use with npx (no installation required)
npx react-pprof profile.pb

CLI Usage

# Basic usage
react-pprof profile.pb

# Custom output file
react-pprof -o flamegraph.html profile.pb

# Help
react-pprof --help

Building CLI Templates

Before using the CLI, build the static templates:

npm run build:cli

This generates optimized HTML templates and JavaScript bundles in the cli-build/ directory.

Supported Profile Formats

The CLI automatically handles both:

  • Gzipped profiles: Common with @datadog/pprof output (auto-detected)
  • Uncompressed profiles: Raw pprof binary data

Example Workflow

# 1. Generate a profile (see examples below)
curl http://localhost:3000/profile > profile.pb

# 2. Build CLI templates (one-time setup)
npm run build:cli

# 3. Generate static HTML flamegraph
react-pprof profile.pb

# 4. Open in browser
open profile.html

The generated HTML includes:

  • Complete React flamegraph visualization
  • Interactive tooltips and stack details
  • WebGL-optimized rendering
  • All profile data embedded (no server required)

Capturing pprof Profiles

Using @datadog/pprof

To capture CPU profiles in Node.js applications, you can use the @datadog/pprof package:

npm install @datadog/pprof

Requirements: Node.js 18 or greater

Basic CPU Profile Capture

const pprof = require('@datadog/pprof')
const fs = require('fs')

// Collect a 10-second wall time profile
const profile = await pprof.time.profile({
  durationMillis: 10000    // Profile for 10 seconds
})

// Or...

pprof.time.start({
  durationMillis: 10000
})

// Do something ...

const profile = pprof.time.stop()

// Encode profile data to buffer
const buf = profile.encode()

// Save profile data to disk
fs.writeFile('cpu-profile.pprof', buf, (err) => {
  if (err) throw err;
  console.log('Profile saved to cpu-profile.pprof')
})

Example Servers

This repository includes example servers to demonstrate profile generation:

Real Profiling Server (example-server.js)

# Start the real profiling server
node example-server.js

# Generate some load to profile
curl http://localhost:3002/load
curl http://localhost:3002/load
curl http://localhost:3002/load

# Download gzipped profile (automatically handled by CLI)
curl http://localhost:3002/profile > real-profile.pb

# Generate flamegraph
react-pprof real-profile.pb

Synthetic Profile Server (simple-server.js)

For testing and demonstration, use the synthetic server that generates compatible pprof data:

# Start the synthetic server
node simple-server.js

# Download synthetic profile
curl http://localhost:3001/profile > synthetic-profile.pb

# Generate flamegraph
react-pprof synthetic-profile.pb

The synthetic server creates realistic function hierarchies and CPU distributions for demonstration purposes.

Components

This package provides several React components for visualizing pprof profiles. Click on each component name for detailed documentation, props, and usage examples:

Core Components

  • FullFlameGraph - Complete flame graph with navigation controls, hottest frames bar, and stack details panel
  • FlameGraph - Core WebGL-powered flame graph visualization component
  • StackDetails - Detailed panel showing stack trace and child frames

Navigation Components

Utility Components

Getting Started

For most use cases, start with FullFlameGraph as it provides a complete profiling interface out of the box. Use the individual components when you need more control over the layout and functionality.

Data Types

FrameData

Represents a single frame in the flame graph.

interface FrameData {
  id: string;           // Unique identifier for the frame
  name: string;         // Function name
  value: number;        // Frame weight/value
  depth: number;        // Stack depth (0 = root)
  x: number;           // Normalized x position (0-1)
  width: number;       // Normalized width (0-1)
  functionName: string; // Function name (same as name)
  fileName?: string;    // Source file name
  lineNumber?: number;  // Source line number
}

FlameNode

Represents a node in the flame graph tree structure.

interface FlameNode {
  id: string;           // Unique identifier
  name: string;         // Function name
  value: number;        // Frame weight/value
  children: FlameNode[]; // Child frames
  parent?: FlameNode;   // Parent frame
  x: number;           // Normalized x position (0-1)
  width: number;       // Normalized width (0-1)
  depth: number;       // Stack depth (0 = root)
  fileName?: string;    // Source file name
  lineNumber?: number;  // Source line number
}

Theming

Both the <FlameGraph /> and <FullFlameGraph /> components accept several color properties to configure their appearance:

  • backgroundColor - Background color of the flame graph
  • textColor - Color of text labels and UI elements
  • primaryColor - Color for root nodes or nodes near 100% of their parent's weight
  • secondaryColor - Color for nodes near 0% of their parent's weight

The flame graph uses a gradient of colors between the primary and secondary colors depending on each frame's weight ratio compared to its parent.

// Traditional Red/Orange theme
<FullFlameGraph
  profile={profile}
  primaryColor="#ff4444"
  secondaryColor="#ffcc66"
  backgroundColor="#1e1e1e"
  textColor="#ffffff"
/>

// Green theme
<FullFlameGraph
  profile={profile}
  primaryColor="#2ecc71"
  secondaryColor="#27ae60"
  backgroundColor="#1e1e1e"
  textColor="#ffffff"
/>

// Blue theme
<FullFlameGraph
  profile={profile}
  primaryColor="#2563eb"
  secondaryColor="#7dd3fc"
  backgroundColor="#2c3e50"
  textColor="#ffffff"
/>

Interactions

Mouse Controls

  • Click Frame: Zoom in to selected frame
  • Click Empty Space: Zoom out to root view
  • Hover Frame: Show tooltip with frame details
  • Mouse Move: Tooltip follows cursor
  • Mouse Leave: Hide tooltip

Keyboard Navigation

The flame graph supports full keyboard navigation for accessibility and power users:

  • Arrow Up (↑): Navigate to the parent frame (zoom out one level in the call stack)
  • Arrow Down (↓): Navigate to the first child frame (zoom into the largest child by value)
  • Arrow Left (←): Navigate to the previous sibling frame (move to the frame before the current one at the same stack level)
  • Arrow Right (→): Navigate to the next sibling frame (move to the frame after the current one at the same stack level)
  • Escape or Home: Reset zoom to show the complete flame graph

The canvas is focusable (tabIndex=0) and includes appropriate ARIA attributes for screen readers. Keyboard navigation automatically zooms to each selected frame and triggers the onFrameClick callback with the appropriate frame data.

Testing

Running Tests

# Run all tests
npm test

# Run tests with UI
npm run test:ui

# Run specific test suites
npm run test:flamegraph
npm run test:stack-details
npm run test:integration

# Update visual snapshots
npm run test:update-snapshots

Test Coverage

  • Unit Tests: Component logic and data processing
  • Integration Tests: Component interaction and communication
  • Visual Regression Tests: Pixel-perfect UI consistency
  • Performance Tests: WebGL performance benchmarks
  • Accessibility Tests: Keyboard navigation and ARIA support

Development

Setup

# Clone repository
git clone https://github.com/platformatic/react-pprof.git
cd react-pprof

# Install dependencies
npm install

# Start development server
npm run storybook