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 🙏

© 2026 – Pkg Stats / Ryan Hefner

vite-plugin-component-debugger

v2.2.0

Published

Highly customizable Vite plugin that adds data attributes to JSX/TSX elements for development tracking, debugging, and testing. Features path filtering, transformers, presets, and more.

Readme

vite-plugin-component-debugger

Vite Plugin Component Debugger

npm version npm downloads GitHub license GitHub stars

Build Status Auto Release TypeScript Vite

Buy Me A Coffee Follow on Twitter

A highly customizable Vite plugin that automatically adds data attributes to JSX/TSX elements during development. Track, debug, and understand component rendering with powerful features like path filtering, attribute transformers, presets, and more. Perfect for AI-generated code and debugging "which component rendered this?" 🤔

✨ What's New in v2.2

Performance Optimizations (v2.2.0):

  • 🚀 15-30% faster build times with 3 micro-optimizations
  • 5-10x faster path matching with pre-compiled glob patterns
  • 📦 2-3x faster metadata encoding with optimized JSON serialization
  • 🔧 Modular architecture - Clean, maintainable 7-file structure

V2 Features - Complete control over component debugging:

  • 🎯 Path Filtering - Include/exclude files with glob patterns
  • 🔧 Attribute Transformers - Customize any attribute value (privacy, formatting)
  • 🎨 Presets - Quick configs for common use cases (minimal, testing, debugging, production)
  • Conditional Tagging - Tag only specific components with shouldTag callback
  • 🏷️ Custom Attributes - Add your own data attributes (git info, environment, etc.)
  • 📦 Metadata Encoding - Choose JSON, Base64, or plain text encoding
  • 📊 Statistics & Callbacks - Track processing stats and export metrics
  • 🎚️ Depth Filtering - Control tagging by component nesting level
  • 🔐 Attribute Grouping - Combine all attributes into single JSON attribute
  • 🗺️ Source Map Hints - Better debugging with source map comments

📚 View Detailed Examples & Use Cases

Quick Start

# Install
pnpm add -D vite-plugin-component-debugger
# or: npm install --save-dev vite-plugin-component-debugger
# or: yarn add -D vite-plugin-component-debugger
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import componentDebugger from "vite-plugin-component-debugger";

export default defineConfig({
  plugins: [
    componentDebugger(), // ⚠️ IMPORTANT: Must be BEFORE react()
    react(),
  ],
});

⚠️ CRITICAL: componentDebugger() must be placed BEFORE react() plugin, otherwise line numbers will be wrong

What It Does

Before:

// src/components/Button.tsx (line 10)
<button className="btn-primary" onClick={handleClick}>
  Click me
</button>

After (Default - All Attributes):

<button
  data-dev-id="src/components/Button.tsx:10:2"
  data-dev-name="button"
  data-dev-path="src/components/Button.tsx"
  data-dev-line="10"
  data-dev-file="Button.tsx"
  data-dev-component="button"
  className="btn-primary"
  onClick={handleClick}
>
  Click me
</button>

After (Minimal Preset - Clean):

componentDebugger({ preset: 'minimal' })

// Results in:
<button
  data-dev-id="src/components/Button.tsx:10:2"
  className="btn-primary"
  onClick={handleClick}
>
  Click me
</button>

After (Custom Filtering):

componentDebugger({
  includeAttributes: ["id", "name", "line"]
})

// Results in:
<button
  data-dev-id="src/components/Button.tsx:10:2"
  data-dev-name="button"
  data-dev-line="10"
  className="btn-primary"
  onClick={handleClick}
>
  Click me
</button>

Key Benefits

  • 🐛 Debug Faster: Find which component renders any DOM element
  • 📍 Jump to Source: Go directly from DevTools to your code
  • 🎯 Stable Testing: Use data attributes for reliable E2E tests
  • Zero Runtime Cost: Only runs during development
  • 🔧 Smart Exclusions: Automatically skips Fragment and Three.js elements

Configuration

Basic Configuration

componentDebugger({
  enabled: process.env.NODE_ENV === "development", // When to run
  attributePrefix: "data-dev", // Custom prefix
  extensions: [".jsx", ".tsx"], // File types
});

Quick Start with Presets

// Minimal - only ID attribute (cleanest DOM)
componentDebugger({ preset: "minimal" });

// Testing - ID, name, component (perfect for E2E)
componentDebugger({ preset: "testing" });

// Debugging - everything + metadata (full visibility)
componentDebugger({ preset: "debugging" });

// Production - privacy-focused with shortened paths
componentDebugger({ preset: "production" });

📚 See all preset details in EXAMPLES.md

Common Configurations

componentDebugger({
  includeAttributes: ["id", "name"], // Only these attributes
});
// Result: Only data-dev-id and data-dev-name

See more attribute filtering examples →

componentDebugger({
  includePaths: ["src/components/**", "src/features/**"],
  excludePaths: ["**/*.test.tsx", "**/*.stories.tsx"],
});

See path filtering patterns →

componentDebugger({
  transformers: {
    path: (p) => p.split("/").slice(-2).join("/"), // Shorten paths
    id: (id) => id.split(":").slice(-2).join(":"), // Remove path from ID
  },
});

See transformer examples →

componentDebugger({
  shouldTag: ({ elementName }) => {
    // Only tag custom components (uppercase)
    return elementName[0] === elementName[0].toUpperCase();
  },
});

See conditional tagging patterns →

💡 Pro Tip: Use includeAttributes for cleaner DOM instead of legacy includeProps/includeContent

⚠️ Gotcha: When both includeAttributes and excludeAttributes are set, includeAttributes takes priority

Configuration Reference

| Option | Type | Default | Description | | ----------------- | ---------- | ------------------ | --------------------------------------------------------------------------- | | enabled | boolean | true | Enable/disable the plugin | | attributePrefix | string | 'data-dev' | Prefix for data attributes | | extensions | string[] | ['.jsx', '.tsx'] | File extensions to process | | preset | Preset | undefined | Quick config: 'minimal' | 'testing' | 'debugging' | 'production' |

| Option | Type | Default | Description | | ------------------- | ----------------- | ----------- | ------------------------------------------------ | | includeAttributes | AttributeName[] | undefined | Recommended: Only include these attributes | | excludeAttributes | AttributeName[] | undefined | Exclude these attributes | | transformers | object | undefined | Transform attribute values (privacy, formatting) | | groupAttributes | boolean | false | Combine all into single JSON attribute |

Available: 'id', 'name', 'path', 'line', 'file', 'component', 'metadata'

→ Full attribute control examples

| Option | Type | Default | Description | | ----------------- | ------------- | -------------------------------- | ------------------------ | | includePaths | string[] | undefined | Glob patterns to include | | excludePaths | string[] | undefined | Glob patterns to exclude | | excludeElements | string[] | ['Fragment', 'React.Fragment'] | Element names to skip | | customExcludes | Set<string> | Three.js elements | Custom elements to skip |

→ Path filtering patterns

| Option | Type | Default | Description | | ------------------ | ---------------------------------- | ----------- | -------------------------------------------- | | shouldTag | (info) => boolean | undefined | Conditionally tag components | | customAttributes | (info) => Record<string, string> | undefined | Add custom attributes dynamically | | metadataEncoding | MetadataEncoding | 'json' | Encoding: 'json' | 'base64' | 'none' |

→ Conditional tagging→ Custom attributes

| Option | Type | Default | Description | | ----------------------- | ----------------- | ----------- | ----------------------- | | maxDepth | number | undefined | Maximum nesting depth | | minDepth | number | undefined | Minimum nesting depth | | tagOnlyRoots | boolean | false | Only tag root elements | | onTransform | (stats) => void | undefined | Per-file callback | | onComplete | (stats) => void | undefined | Completion callback | | exportStats | string | undefined | Export stats to file | | includeSourceMapHints | boolean | false | Add source map comments | | debug | boolean | false | Enable debug logging |

→ Depth filtering→ Statistics

💡 All v2 features are opt-in - Existing configs work unchanged

📖 See complete TypeScript types: import { type TagOptions } from 'vite-plugin-component-debugger'

📚 View 50+ Detailed Examples in EXAMPLES.md →

Examples include: E2E testing setups, debug overlays, monorepo configs, feature flags, performance monitoring, and more!

Use Cases

1. Development Debugging (Simple)

Find components in the DOM:

// In browser console
document.querySelectorAll('[data-dev-component="Button"]');
console.log("Button locations:", [...$$('[data-dev-path*="Button"]')]);

2. E2E Testing (Intermediate)

Stable selectors for tests:

// Cypress
cy.get('[data-dev-component="SubmitButton"]').click();
cy.get('[data-dev-path*="LoginForm"]').should("be.visible");

// Playwright
await page.click('[data-dev-component="SubmitButton"]');
await expect(page.locator('[data-dev-path*="LoginForm"]')).toBeVisible();

3. Visual Debugging Tools (Advanced)

Build custom debugging overlays:

// Show component boundaries on hover
document.addEventListener("mouseover", (e) => {
  const target = e.target;
  if (target.dataset?.devComponent) {
    target.style.outline = "2px solid red";
    console.log(`Component: ${target.dataset.devComponent}`);
    console.log(`Location: ${target.dataset.devPath}:${target.dataset.devLine}`);
  }
});

4. Performance Monitoring (Expert)

Track component render activity:

const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.type === "childList") {
      mutation.addedNodes.forEach((node) => {
        if (node.dataset?.devId) {
          console.log(`Component rendered: ${node.dataset.devId}`);
        }
      });
    }
  });
});

observer.observe(document.body, { childList: true, subtree: true });

Advanced Features

Environment-Specific Setup

// Different configs per environment
const isDev = process.env.NODE_ENV === "development";
const isStaging = process.env.NODE_ENV === "staging";

export default defineConfig({
  plugins: [
    componentDebugger({
      enabled: isDev || isStaging,
      attributePrefix: isStaging ? "data-staging" : "data-dev",
      includeProps: isDev, // Enable metadata in development
      includeContent: isDev, // Enable content capture in development
    }),
    react(),
  ],
});

React Three Fiber Support

Automatically excludes Three.js elements:

// Default exclusions
componentDebugger({
  customExcludes: new Set([
    "mesh",
    "group",
    "scene",
    "camera",
    "ambientLight",
    "directionalLight",
    "pointLight",
    "boxGeometry",
    "sphereGeometry",
    "planeGeometry",
    "meshBasicMaterial",
    "meshStandardMaterial",
    // ... and many more
  ]),
});

// To include Three.js elements
componentDebugger({
  customExcludes: new Set(), // Empty set = tag everything
});

TypeScript Support

Full type definitions included:

import componentDebugger, { type TagOptions } from "vite-plugin-component-debugger";

const config: TagOptions = {
  enabled: true,
  attributePrefix: "data-track",
};

export default defineConfig({
  plugins: [componentDebugger(config), react()],
});

Build Performance & Statistics

📊 Component Debugger Statistics:
   Total files scanned: 45
   Files processed: 32
   Elements tagged: 287

Performance optimizations (v2.2.0):

  • 🚀 15-30% faster than v2.1 with 3 micro-optimizations
  • Pre-compiled glob patterns - 5-10x faster path matching
  • 📦 Optimized JSON serialization - 2-3x faster metadata encoding
  • 🔧 Smart string operations - 2x faster debug logging
  • Time savings: 200-500ms on 100-file projects, 2-5s on 1000-file projects
  • Efficient AST traversal with caching
  • Minimal HMR impact
  • Automatically skips node_modules
  • Only runs during development

Troubleshooting & Common Gotchas

Problem: data-dev-line shows numbers ~19 higher than expected

Cause: Plugin order is wrong - React plugin adds ~19 lines of imports/HMR setup

Fix: Move componentDebugger() BEFORE react() in Vite config

// ❌ WRONG - Line numbers will be offset
export default defineConfig({
  plugins: [
    react(), // Transforms code first, adds ~19 lines
    componentDebugger(), // Gets wrong line numbers
  ],
});

// ✅ CORRECT - Accurate line numbers
export default defineConfig({
  plugins: [
    componentDebugger(), // Processes original source first
    react(), // Transforms after tagging
  ],
});
  1. Check file extension: File must match extensions (default: .jsx, .tsx)
  2. Check exclusions: Element not in excludeElements or customExcludes
  3. Check paths: File not excluded by excludePaths pattern
  4. Check plugin order: componentDebugger() before react()
  5. Check enabled: Plugin is enabled (enabled: true)
  6. Check shouldTag: If using shouldTag, callback must return true

Debug with:

componentDebugger({
  debug: true, // Shows what's being processed
  enabled: true,
});

Quick fixes:

  1. Use includeAttributes to reduce DOM size:
    includeAttributes: ["id", "name"]; // Only essential attributes
  2. Filter paths to only process needed directories:
    includePaths: ['src/components/**'],
    excludePaths: ['**/*.test.tsx', '**/*.stories.tsx']
  3. Use maxDepth to limit deep nesting:
    maxDepth: 5; // Only tag up to 5 levels deep
  4. Skip test files with excludePaths

→ See performance optimization examples

componentDebugger({
  enabled: process.env.NODE_ENV !== "production",
});

Or use environment-specific configs:

enabled: isDev || isStaging, // Not in production

Gotcha: When both are set, includeAttributes takes priority

componentDebugger({
  includeAttributes: ["id", "name", "line"],
  excludeAttributes: ["name"], // ⚠️ This is IGNORED
});
// Result: Only id, name, line are included

Best practice: Use one or the other, not both

Import types for full IntelliSense:

import componentDebugger, {
  type TagOptions,
  type ComponentInfo,
  type AttributeName,
} from "vite-plugin-component-debugger";

const config: TagOptions = {
  // Full type checking
};

Development & Contributing

Auto-Release Workflow

🚀 Every commit to main triggers automatic release:

Commit Message → Version Bump:

  • BREAKING CHANGE: or major: → Major (1.0.0 → 2.0.0)
  • feat: or feature: or minor: → Minor (1.0.0 → 1.1.0)
  • Everything else → Patch (1.0.0 → 1.0.1)

Example commit messages:

# Major version (breaking changes)
git commit -m "BREAKING CHANGE: removed deprecated API"
git commit -m "major: complete rewrite of plugin interface"

# Minor version (new features)
git commit -m "feat: add TypeScript 5.0 support"
git commit -m "feature: new configuration option for props"
git commit -m "minor: add custom exclude patterns"

# Patch version (bug fixes, docs, chores)
git commit -m "fix: resolve memory leak in transformer"
git commit -m "docs: update README examples"
git commit -m "chore: update dependencies"

# Skip release
git commit -m "docs: fix typo [skip ci]"

What happens automatically:

  1. Tests run, package builds
  2. Version bump based on commit message
  3. GitHub release created with changelog
  4. Package published to npm

Setup auto-publishing:

  1. Get NPM token: npm token create --type=automation
  2. Add to GitHub repo: SettingsSecretsNPM_TOKEN
  3. Commit to main branch to trigger first release

Contributing

  1. Fork and clone
  2. pnpm install
  3. Make changes and add tests
  4. pnpm run check (lint + test + build)
  5. Commit with semantic message (see above)
  6. Open PR

See .github/COMMIT_CONVENTION.md for examples.

Development Setup

git clone https://github.com/yourusername/vite-plugin-component-debugger.git
cd vite-plugin-component-debugger
pnpm install
pnpm run test     # Run tests
pnpm run build    # Build package
pnpm run check    # Full validation

Author & Support

Tonye Brown - Builder, Front-end developer, designer, and performance optimization expert crafting immersive web experiences. Also a Music Producer and Artist.

Connect:

Support This Project:

  • ⭐ Star this repository
  • Buy me a coffee
  • 💝 Sponsor on GitHub
  • 🐛 Report issues or suggest features
  • 🤝 Contribute code via pull requests
  • 📢 Share with other developers

License

MIT © Tonye Brown


Made with ❤️ by Tonye Brown

Inspired by lovable-tagger, enhanced for the Vite ecosystem.

GitHub Website LinkedIn

⭐ Star this repo if it helped you!