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-devtools-metadata

v1.1.0

Published

Comprehensive React component metadata injection with performance tracking, source location, props, and more

Readme

React DevTools Metadata

🚀 Zero-config metadata injection for React components - Just add the plugin and go!

npm version License: MIT

✨ Zero Configuration

No imports. No setup code. Just add the plugin.

npm install --save-dev react-devtools-metadata
// vite.config.js
import reactMetadata from 'react-devtools-metadata/vite'

export default defineConfig({
  plugins: [react(), reactMetadata()]
})

That's it! Everything works automatically.

Features

  • Zero Configuration - Just add the plugin
  • Absolute File Paths - No manual project root setup
  • Exact Line & Column Numbers - Pinpoint accuracy
  • Performance Metrics - Automatic render time tracking
  • Props Inspection - Runtime props available
  • Git Integration - Optional commit information (enable with git: true)
  • Multiple Bundlers - Babel, Vite, Webpack support
  • Zero Production Overhead - Automatically disabled in production

Installation

npm install --save-dev react-devtools-metadata

Quick Start

Vite

// vite.config.js
import react from '@vitejs/plugin-react';
import reactMetadata from 'react-devtools-metadata/vite';

export default defineConfig({
  plugins: [
    react(),
    reactMetadata()  // ✅ That's it!
  ]
});

Optional configuration:

reactMetadata({
  performance: true,  // Track render performance (default: true)
  debug: false,       // Log transformation details (default: false)
  git: false          // Include git blame info (default: false, slower)
})

Webpack / Create React App

// babel.config.js
module.exports = {
  presets: ['@babel/preset-react'],
  env: {
    development: {
      plugins: ['react-devtools-metadata/babel']  // ✅ That's it!
    }
  }
};

Optional configuration:

plugins: [
  ['react-devtools-metadata/babel', {
    performance: true,  // Track performance (default: true)
    debug: false,       // Log details (default: false)
    git: false          // Include git info (default: false)
  }]
]

Next.js

// next.config.js
module.exports = {
  webpack: (config, { dev, isServer }) => {
    if (dev && !isServer) {
      config.module.rules.push({
        test: /\.(jsx|tsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            plugins: [['react-devtools-metadata/babel', { performance: true }]]
          }
        }
      });
    }
    return config;
  }
};

What You Get

Before

// Limited React internal data
{
  componentName: "MyComponent",
  fileName: "Unknown"
}

After

// Complete metadata + performance tracking
{
  componentName: "MyComponent",
  displayName: "MyComponent",
  fileName: "MyComponent.jsx",
  filePath: "src/components/MyComponent.jsx",
  absolutePath: "/Users/you/project/src/components/MyComponent.jsx",
  lineNumber: 15,
  columnNumber: 0,
  
  // Performance metrics
  performance: {
    renderCount: 5,
    totalRenderTime: 45.2,
    averageRenderTime: 9.04,
    lastRenderTime: 8.5,
    slowRenderWarnings: 0,
    firstRenderAt: 1701234567890,
    lastRenderAt: 1701234568123
  },
  
  // Props (runtime)
  props: {
    title: "Hello World",
    count: 42,
    onClick: "[Function]"
  },
  
  // Git info (optional)
  git: {
    lastCommit: "abc123",
    lastAuthor: "John Doe",
    lastModified: "2024-01-15"
  }
}

Browser Extension Integration

// In your Chrome extension's content script
function extractComponentMetadata(fiber) {
  const component = fiber.type;
  
  // Get injected metadata
  const metadata = component?.__devMetadata;
  
  if (metadata) {
    console.log('Component:', metadata.componentName);
    console.log('File:', metadata.absolutePath);
    console.log('Line:', metadata.lineNumber);
    console.log('Renders:', metadata.performance.renderCount);
    console.log('Avg Time:', metadata.performance.averageRenderTime + 'ms');
  }
  
  // Get runtime props from fiber
  const props = extractProps(fiber.memoizedProps);
  
  return { ...metadata, props };
}

Runtime Performance Tracking

The library automatically tracks component performance:

// Access performance data
const component = MyComponent;
const perf = component.__devMetadata.performance;

console.log(`Rendered ${perf.renderCount} times`);
console.log(`Average: ${perf.averageRenderTime}ms`);
console.log(`Last render: ${perf.lastRenderTime}ms`);

// Check for slow renders (>16ms)
if (perf.slowRenderWarnings > 0) {
  console.warn(`⚠️ ${perf.slowRenderWarnings} slow renders detected!`);
}

Configuration Options

Vite Plugin Options

interface VitePluginOptions {
  // Enable/disable the plugin (default: process.env.NODE_ENV === 'development')
  enabled?: boolean;
  
  // Track performance metrics
  performance?: boolean;
  
  // Include git blame information (slower, requires git)
  git?: boolean;
  
  // Use source maps for original locations
  sourceMaps?: boolean;
  
  // Include file patterns (default: /\.(jsx|tsx)$/)
  include?: RegExp | RegExp[];
  
  // Exclude file patterns (default: /node_modules/)
  exclude?: RegExp | RegExp[];
  
  // Custom metadata extractor
  customMetadata?: (filepath: string) => Record<string, any>;
}

Babel Plugin Options

interface BabelPluginOptions {
  // Track performance metrics
  performance?: boolean;
  
  // Include git information
  git?: boolean;
  
  // Use source maps
  sourceMaps?: boolean;
  
  // Project root (default: process.cwd())
  projectRoot?: string;
  
  // Custom metadata
  customMetadata?: (filepath: string, state: any) => Record<string, any>;
}

Performance Impact

Build Time

  • Babel plugin: +5-10% build time
  • Vite plugin: +2-5% build time (minimal)

Runtime

  • Development: Negligible (<1ms per component mount)
  • Production: Zero (plugin disabled)

Bundle Size

  • Development: +2-5KB per component (metadata only)
  • Production: 0KB (stripped by bundler)

Advanced Features

Custom Metadata

Add your own metadata to components:

// vite.config.js
reactMetadata({
  customMetadata: (filepath) => ({
    team: filepath.includes('/team-a/') ? 'Team A' : 'Team B',
    feature: extractFeatureFromPath(filepath),
    lastModified: fs.statSync(filepath).mtime
  })
})

Integration with React DevTools

// Expose to React DevTools
if (typeof window !== 'undefined') {
  window.__REACT_DEVTOOLS_METADATA__ = {
    getComponentMetadata: (fiber) => fiber.type?.__devMetadata,
    getAllComponents: () => {
      // Scan fiber tree and collect all metadata
    }
  };
}

Performance Monitoring Dashboard

// Create a performance dashboard
function PerformanceDashboard() {
  const [components, setComponents] = useState([]);
  
  useEffect(() => {
    // Collect all component metadata
    const metadata = collectAllComponentMetadata();
    
    // Sort by render count or average time
    const sorted = metadata.sort((a, b) => 
      b.performance.renderCount - a.performance.renderCount
    );
    
    setComponents(sorted);
  }, []);
  
  return (
    <div>
      {components.map(comp => (
        <div key={comp.componentName}>
          <h3>{comp.componentName}</h3>
          <p>Renders: {comp.performance.renderCount}</p>
          <p>Avg Time: {comp.performance.averageRenderTime}ms</p>
        </div>
      ))}
    </div>
  );
}

TypeScript Support

Full TypeScript support with type definitions:

import type { ComponentMetadata, PerformanceMetrics } from 'react-devtools-metadata/runtime';

function inspectComponent(fiber: any): ComponentMetadata | null {
  return fiber.type?.__devMetadata || null;
}

Debugging

Enable debug logging:

// vite.config.js
reactMetadata({
  debug: true  // Logs metadata injection details
})

Troubleshooting

Metadata not showing up?

  1. Check environment: Plugin only runs in development

    console.log(process.env.NODE_ENV); // Should be 'development'
  2. Verify plugin is loaded:

    // Should see plugin output in build logs
    npm run dev -- --debug
  3. Check component detection:

    // Component names must start with uppercase
    function MyComponent() {} // ✅ Works
    function myComponent() {} // ❌ Not detected

Performance tracking not working?

Ensure performance: true is set in plugin options:

reactMetadata({ performance: true })

Source maps not resolving?

  1. Enable source maps in your bundler config
  2. Set sourceMaps: true in plugin options
  3. Check that .map files are generated

Examples

See the /examples directory for complete working examples:

API Reference

Runtime API

// Get metadata from component
function getComponentMetadata(component: React.ComponentType): ComponentMetadata | null;

// Get metadata from fiber
function getMetadataFromFiber(fiber: Fiber): ComponentMetadata | null;

// Extract safe props
function extractSafeProps(props: any): Record<string, any>;

// Performance tracking
function trackRender(componentName: string, renderTime: number): void;
function getPerformanceMetrics(componentName: string): PerformanceMetrics | null;

Types

interface ComponentMetadata {
  componentName: string;
  displayName?: string;
  fileName: string;
  filePath: string;
  absolutePath: string;
  lineNumber: number;
  columnNumber: number;
  performance?: PerformanceMetrics;
  props?: Record<string, any>;
  git?: GitInfo;
  timestamp: number;
}

interface PerformanceMetrics {
  renderCount: number;
  totalRenderTime: number;
  averageRenderTime: number;
  lastRenderTime: number;
  slowRenderWarnings: number;
  firstRenderAt: number;
  lastRenderAt: number;
}

interface GitInfo {
  lastCommit: string;
  lastAuthor: string;
  lastModified: string;
  branch?: string;
}

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.

License

MIT © [Your Name]

Changelog

See CHANGELOG.md for release history.

Related Projects

Support