Skip to content

hyperse-io/code-inspector

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Hyperse Inspector

@hyperse/inspector is the tool for seamlessly navigating from your browser to your IDE. With just a simple click, you can jump from a React component in the browser to its source code in your local IDE instantly. Think of it as a supercharged version of Chrome's Inspector, tailored for developers.

Build Version Top Language License

Table of Contents

Why @hyperse/inspector?

Have you ever run into any of these issues 🤔:

  • You need to fix bugs in a team project, but you're lost trying to find where the page/component's code is located.
  • You're excited to explore an open-source project, but struggle to pinpoint the implementation of a specific page or component.
  • You're thinking about a component and want a quick peek at its code, without memorizing or manually navigating through deeply nested file paths.

That's exactly why @hyperse/inspector was created – to make your development workflow smoother and more efficient!

Features

  • Instant Code Navigation: Click on a UI element in the browser and jump directly to its source code in your IDE.
  • 🔌 IDE Integration: Launches your configured IDE/Editor pointing to the exact file and line number.
  • 🛠️ Multi-framework Support: Works with popular bundlers and frameworks like Vite, Webpack, Rspack, and more.
  • 🚀 Native SWC Plugin: Includes a high-performance SWC plugin for projects using SWC.
  • ⚛️ React 19 Ready: Compatible with the latest React versions, including React 19.
  • ⌨️ Customizable Hotkeys: Change the activation hotkey to fit your preferences.
  • 🌍 Universal: Designed to work with various project setups.

Default Hotkeys

  • macOS: ⌘ + i
  • Windows/Linux: Ctrl + i

You can customize the hotkeys by passing the keys prop to the <Inspector/> component.

Installation

Choose your preferred package manager:

# npm
npm install --save-dev @hyperse/inspector @hyperse/inspector-middleware @hyperse/inspector-babel-plugin # or @hyperse/inspector-swc-plugin
# For Next.js projects, also install:
npm install --save-dev @hyperse/next-inspector

# yarn
yarn add --dev @hyperse/inspector @hyperse/inspector-middleware @hyperse/inspector-babel-plugin # or @hyperse/inspector-swc-plugin
# For Next.js projects, also install:
yarn add --dev @hyperse/next-inspector

# pnpm
pnpm add --save-dev @hyperse/inspector @hyperse/inspector-middleware @hyperse/inspector-babel-plugin # or @hyperse/inspector-swc-plugin
# For Next.js projects, also install:
pnpm add --save-dev @hyperse/next-inspector

How to Use and Configure

Setting up @hyperse/inspector involves a few steps:

Step 1: Install Packages

(Covered in the Installation section above.) Make sure you install:

  1. @hyperse/inspector: The core React component.
  2. @hyperse/inspector-middleware: The dev server middleware.
  3. Either @hyperse/inspector-babel-plugin (for Babel users) or @hyperse/inspector-swc-plugin (for SWC users).
  4. For Next.js projects, also install:
    • @hyperse/next-inspector: The Next.js plugin

Step 2: Add the Inspector Component to Your App

Import and render the <Inspector /> component in your application's root or main layout component. It's a good practice to only include it during development.

// src/App.tsx or your main layout component
import { Inspector } from '@hyperse/inspector';
import { useState } from 'react'; // Optional: for controlled mode

export default function App() {
  // Optional: for controlled mode
  const [inspectorActive, setInspectorActive] = useState(false);

  // Conditionally render the Inspector only in development
  const isDevelopment = process.env.NODE_ENV === 'development';

  return (
    <div>
      {isDevelopment && (
        <Inspector
        // Optional: Customize hotkeys
        // keys={['Control', 'Shift', 'i']}
        // Optional: Controlled mode
        // active={inspectorActive}
        // onActiveChange={setInspectorActive}
        />
      )}
      {/* Your other application components */}
    </div>
  );
}

Step 3: Configure the Build Tool Plugin (Babel or SWC)

This plugin injects necessary source location information into your JSX elements during the build process.

For Babel Users (@hyperse/inspector-babel-plugin)

Add @hyperse/inspector-babel-plugin to your Babel configuration (e.g., babel.config.js or .babelrc.js).

// babel.config.js
module.exports = {
  presets: [
    '@babel/preset-env',
    '@babel/preset-typescript',
    ['@babel/preset-react', { runtime: 'automatic' }],
  ],
  plugins: [
    // Add the inspector plugin only in development mode
    process.env.NODE_ENV === 'development' && '@hyperse/inspector-babel-plugin',
    // Filter out falsy values in case NODE_ENV is not 'development'
  ].filter(Boolean),
};

For SWC Users (@hyperse/inspector-swc-plugin)

Add @hyperse/inspector-swc-plugin to your SWC configuration (e.g., .swcrc or within your bundler's SWC loader options).

Example for .swcrc:

{
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "transform": {
      "react": {
        "runtime": "automatic"
      }
    },
    "experimental": {
      "plugins": [["@hyperse/inspector-swc-plugin", {}]]
    }
  }
}

Note: Ensure the SWC plugin is only applied in development if configuring through bundler options.

Step 4: Configure the Dev Server Middleware

The middleware listens for requests from the inspector component and launches your IDE.

Next.js

For Next.js projects, you can use the official @hyperse/next-inspector plugin. Here's how to configure it:

// next.config.mjs
import { resolve } from 'path';
import { createNextConfig } from '@hyperse/next-config';
import withNextInspector from '@hyperse/next-inspector/plugin';

const plugins = [
  withNextInspector({
    projectCwd: resolve(process.cwd()),
    trustedEditor: 'cursor', // or 'vscode', 'webstorm', etc.
    customLaunchEditorEndpoint: '/hps_inspector',
    keys: ['$mod', 'g'], // Customize hotkeys
    hideDomPathAttr: false,
  }),
];

const nextConfig = {
  // Your Next.js config options
};

export default createNextConfig(nextConfig, plugins);

Key configuration options for Next.js:

  • projectCwd: Your project's root directory
  • trustedEditor: Your preferred IDE (e.g., 'cursor', 'vscode', 'webstorm')
  • customLaunchEditorEndpoint: Custom endpoint for launching the editor
  • keys: Custom hotkey configuration
  • hideDomPathAttr: Whether to hide DOM path attributes in production

Webpack

In your webpack.config.js (or equivalent for development):

// webpack.config.js
const { createInspectorMiddleware } = require('@hyperse/inspector-middleware');

module.exports = (env, argv) => {
  const isDev = argv.mode === 'development';

  return {
    // ... other webpack config
    devServer: {
      // ... other devServer config
      setupMiddlewares: (middlewares, devServer) => {
        if (isDev) {
          /**
           * @hyperse/inspector server middleware
           */
          middlewares.unshift(createInspectorMiddleware({}));
        }
        // Your other middlewares
        return middlewares;
      },
    },
    module: {
      rules: [
        // Example for Babel loader (ensure Step 3 is configured)
        {
          test: /\.(js|jsx|ts|tsx)$/,
          exclude: /node_modules/,
          use: {
            loader: 'babel-loader',
            // Babel options can be here or in babel.config.js
          },
        },
        // Example for SWC loader (ensure Step 3 is configured if using .swcrc, or configure plugin here)
        // {
        //   test: /\.tsx?$/,
        //   exclude: /node_modules/,
        //   use: {
        //     loader: 'swc-loader', // or 'builtin:swc-loader' for Rspack/Turbopack
        //     options: { // SWC options, including the plugin if not using .swcrc
        //       jsc: {
        //         experimental: {
        //           plugins: isDev ? [['@hyperse/inspector-swc-plugin', {}]] : [],
        //         },
        //         // ... other jsc options
        //       },
        //     },
        //   },
        // },
      ],
    },
    // ... other webpack config
  };
};

Vite

In your vite.config.ts (or .js):

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { createInspectorMiddleware } from '@hyperse/inspector-middleware'; // Corrected package

export default defineConfig(({ mode }) => {
  const isDevelopment = mode === 'development';

  return {
    plugins: [
      react({
        // If using Babel for JSX transformation with Vite:
        babel: {
          plugins: [isDevelopment && '@hyperse/inspector-babel-plugin'].filter(
            Boolean
          ),
        },
        // If using SWC (default for @vitejs/plugin-react v3+),
        // ensure @hyperse/inspector-swc-plugin is in your .swcrc
        // or configure it via swc options if available in plugin-react.
      }),
      // Middleware for @hyperse/inspector
      isDevelopment && {
        name: 'hyperse-inspector-middleware',
        configureServer(server) {
          server.middlewares.use(createInspectorMiddleware({}));
        },
      },
    ].filter(Boolean),
    // ... other Vite config
  };
});

For SWC with Vite: If @vitejs/plugin-react uses SWC, ensure @hyperse/inspector-swc-plugin is configured in your project's .swcrc file. Vite's React plugin will pick it up.

Rspack

In your rspack.config.js (or equivalent for development):

// rspack.config.js
const { createInspectorMiddleware } = require('@hyperse/inspector-middleware');

module.exports = (env, argv) => {
  const isDev = process.env.NODE_ENV === 'development'; // Rspack often uses NODE_ENV

  return {
    // ... other Rspack config
    devServer: {
      // ... other devServer config
      setupMiddlewares: (middlewares, devServer) => {
        if (isDev) {
          /**
           * @hyperse/inspector server middleware
           */
          middlewares.unshift(createInspectorMiddleware({}));
        }
        // Your other middlewares
        return middlewares;
      },
    },
    module: {
      rules: [
        // Example for builtin:swc-loader (ensure Step 3 is configured for SWC)
        {
          test: /\.(js|jsx|ts|tsx)$/,
          exclude: /node_modules/,
          loader: 'builtin:swc-loader',
          options: {
            jsc: {
              parser: { syntax: 'typescript', tsx: true },
              transform: { react: { runtime: 'automatic' } },
              experimental: {
                plugins: isDev ? [['@hyperse/inspector-swc-plugin', {}]] : [],
              },
            },
          },
        },
      ],
    },
    // ... other Rspack config
  };
};

Customization

Custom Hotkeys

You can customize the activation hotkeys by passing the keys prop to the <Inspector /> component. The keys prop accepts an array of strings representing KeyboardEvent.key values.

<Inspector keys={['Shift', 'Alt', 'c']} />

This will set the hotkey to Shift + Alt + c.

Controlled Mode

For more fine-grained control over the inspector's visibility, you can use the active and onActiveChange props.

import { Inspector } from '@hyperse/inspector';
import { useState } from 'react';

function MyComponent() {
  const [showInspector, setShowInspector] = useState(false);

  return (
    <>
      <button onClick={() => setShowInspector(!showInspector)}>
        Toggle Inspector Programmatically
      </button>
      <Inspector
        active={showInspector}
        onActiveChange={setShowInspector}
        // You can still provide custom keys or use default
      />
    </>
  );
}

How It Works

Here's a simplified overview of the @hyperse/inspector pipeline:

sequenceDiagram
  autonumber
  participant Dev as Developer Browser
  participant UI as Inspector Component (client)
  participant Trans as Babel/SWC Plugin (build)
  participant MW as Dev Server Middleware
  participant Launch as Launcher (e.g., launch-editor)
  participant IDE as IDE

  rect rgb(240,245,255)
    note over Trans: Build-time transformation
    Trans->>Trans: Inject data-hps-* attrs (filename:line:col)
  end

  Dev->>UI: Press hotkey / click inspect
  UI->>MW: HTTP request with file, line, column
  alt Valid request
    MW->>Launch: Spawn editor with file:line:col
    Launch->>IDE: Open at location
    IDE-->>Dev: File focused at target
  else Invalid/unknown
    MW-->>UI: Error response
    UI-->>Dev: Show error state
  end
Loading

  1. Part 0: JSX Source Information (Build-time)

    • This step is typically handled by your existing React setup (e.g., via Babel's babel-plugin-transform-react-jsx-source or SWC's equivalent functionality). It adds __source (file path, line number) debug information to JSX elements.
    • The @hyperse/inspector-babel-plugin or @hyperse/inspector-swc-plugin leverages this or injects similar information, ensuring it's consistently available and formatted for the inspector.
  2. Part 1: Inspector Component (Client-side)

    • The <Inspector /> component, when activated (e.g., by hotkey), allows you to select an element on the page.
    • Upon selection, it reads the source location information (file path, line, column) embedded in the selected React component's DOM element or Fiber node.
    • It then sends an API request to your development server, containing this source path information.
  3. Part 2: Dev Server Middleware (Server-side)

    • The @hyperse/inspector-middleware (e.g., createInspectorMiddleware) runs on your development server.
    • It listens for API requests from the client-side Inspector.
    • When it receives a request, it uses a launcher utility (like launch-editor) to open the specified source file in your configured local IDE/Editor, navigating directly to the correct line and column.

Supported IDEs/Editors

@hyperse/inspector uses launch-editor (or a similar mechanism) under the hood, which supports a wide range of popular IDEs and editors. Commonly supported ones include:

  • Visual Studio Code (VS Code)
  • WebStorm / IntelliJ IDEA / PhpStorm / PyCharm (and other JetBrains IDEs)
  • Sublime Text
  • Atom
  • Vim / Neovim
  • Emacs
  • And more...

Ensure your chosen IDE is correctly configured in your system's environment variables (e.g., LAUNCH_EDITOR or EDITOR) or that its command-line interface (CLI) is in your system's PATH. For VS Code, simply having code in your PATH is usually sufficient.

Troubleshooting

  • Inspector not opening files / "Editor not found":
    • Ensure your IDE's command-line tool is installed and added to your system's PATH (e.g., code for VS Code).
    • You might need to set the LAUNCH_EDITOR or EDITOR environment variable. For example, in your .bashrc or .zshrc:
      export LAUNCH_EDITOR=code # For VS Code
      # export LAUNCH_EDITOR=webstorm # For WebStorm
    • Restart your development server and terminal after making changes to environment variables.
  • Component source not found / incorrect location:
    • Verify that the Babel or SWC plugin is correctly configured and running only in development mode.
    • Ensure source maps are being generated correctly if the plugin relies on them indirectly.
    • Check for any conflicting Babel/SWC plugins that might interfere with source information.

License

This project is licensed under the MIT LICENSE.

Related Projects