Awesome Open Source
Awesome Open Source

React Dev Inspector

NPM Version NPM Downloads Node.js License

Introduction

This package allows users to jumping to local IDE code directly from browser React component by just a simple click, which is similar to Chrome inspector but more advanced.

Preview

online demo: https://react-dev-inspector.zthxxx.me

press toggle hotkey (ctrl⌃ + shift⇧ + commmand⌘ + c) then move mouse and click to try it out.

screen record gif (8M size):

inspector-gif

Installation

npm i -D react-dev-inspector

Usage

Users need to add React component and some other webpac config to perform 'react-dev-inspector' in your own projects.

Note: It should be limited to use this package in production mode, as the same as React component and webpack config


Use Inspector React Component

import React from 'react'
import { Inspector, InspectParams } from 'react-dev-inspector'

const InspectorWrapper = process.env.NODE_ENV === 'development'
  ? Inspector
  : React.Fragment

export const Layout = () => {
  // ...

  return (
    <InspectorWrapper
      // props docs see:
      // https://github.com/zthxxx/react-dev-inspector#inspector-component-props
      keys={['control', 'shift', 'command', 'c']}
      disableLaunchEditor={false}
      onHoverElement={(params: InspectParams) => {}}
      onClickElement={(params: InspectParams) => {}}
    >
     <YourComponent>
       ...
     </YourComponent>
    </InspectorWrapper>
  )
}


Set Webpack Config

raw webpack config

A typical raw webpack config is shown below.

In this config, we add:

  • an "inspector-loader"
  • a "DefinePlugin" to get current working directory
  • a "devServer" api middleware to open IDE on when it be called
import { Configuration, DefinePlugin } from 'webpack'
import { createLaunchEditorMiddleware } from 'react-dev-inspector/plugins/webpack'


const config: Configuration = {
  // ...

  /**
   * [compile time] for inject source code file info
   */
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.[jt]sx$/,
        exclude: [
          /node_modules/,
          /file-you-want-exclude/,
        ],
        use: [
          {
            loader: 'react-dev-inspector/plugins/webpack/inspector-loader',
            options: [{
              // loader options docs see:
              // https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
              exclude: [
                'xxx-file-will-be-exclude',
                /regexp-to-match-file /,
              ],
              babelPlugins: [],
              babelOptions: {},
            }],
          },
        ],
      },
    ],
  },

  /**
   * [compile time] for inject current working directory which used in web page runtime
   */
  plugins: [
    new DefinePlugin({
      'process.env.PWD': JSON.stringify(process.cwd()),
    }),
  ],

  /**
   * [server side] webpack dev server side middleware for launch IDE app
   */
  devServer: {
    before: (app) => {
      app.use(createLaunchEditorMiddleware())
    },
  },
}

It seems like the webpack config is too 'complicated', thus some integrated plugins / helper is provided for quick trial if your project happen to use these utils / frameworks.

So here are some ways for alternative the raw webpack config listed below:


usage with webpack-chain

This is almost equivalent to raw webpack config above,

but it will NOT override devServer.before, just add middleware before origin devServer.before

import { inspectorChainWebpack } from 'react-dev-inspector/plugins/webpack'


webpackChainConfig = inspectorChainWebpack(webpackChainConfig, {
  // loader options docs see:
  // https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
  exclude: [],
  babelPlugins: [],
  babelOptions: {},
})

usage with Umi3

This is also equivalent to usage with webpack-chain

Example .umirc.dev.ts:

// https://umijs.org/config/
import { defineConfig } from 'umi'

export default defineConfig({
  plugins: [
    'react-dev-inspector/plugins/umi/react-inspector',
  ],
  inspectorConfig: {
    // loader options docs see:
    // https://github.com/zthxxx/react-dev-inspector#inspector-loader-props
    exclude: [],
    babelPlugins: [],
    babelOptions: {},
  },
})

usage with Umi2

Example .umirc.dev.js:

import { inspectorChainWebpack } from 'react-dev-inspector/plugins/webpack'

export default {
  // ...
  chainWebpack(config) {
    inspectorChainWebpack(config, {
      // ... options
    })
    return config
  },

  /**
   * And you need to set `false` to `dll` in `umi-plugin-react`,
   * becase these is a umi2 bug that `dll` cannot work with `devServer.before`
   *
   * https://github.com/umijs/umi/issues/2599
   * https://github.com/umijs/umi/issues/2161
   */
}

Configuration

<Inspector> Component Props

typescript define you can see in react-dev-inspector/es/Inspector.d.ts

Property Description Type Default
keys inspector toggle hotkeys

supported keys see: https://github.com/jaywcjlove/hotkeys#supported-keys
string[] ['control', 'shift', 'command', 'c']
disableLaunchEditor whether disable click react component to open IDE for view component code

(launchEditor by default only support be used with react-dev-inpector plugins in dev)
boolean false
onHoverElement triggered while inspector start and mouse hover in a HTMLElement (params: InspectParams) => void -
onClickElement triggered while inspector start and mouse click on a HTMLElement (params: InspectParams) => void -
// import type { InspectParams } from 'react-dev-inspector'

interface InspectParams {
  /** hover / click event target dom element */
  element: HTMLElement,
  /** nearest named react component fiber for dom element */
  fiber?: React.Fiber,
  /** source file line / column / path info for react component */
  codeInfo?: {
    lineNumber: string,
    columnNumber: string,
    relativePath: string,
  },
  /** react component name for dom element */
  name?: string,
}

Inspector Loader Props

// import type { ParserPlugin, ParserOptions } from '@babel/parser'
// import type { InspectorConfig } from 'react-dev-inspector/plugins/webpack'

interface InspectorConfig {
  /** patterns to exclude matched files */
  exclude?: (string | RegExp)[],
  /**
   * add extra plugins for babel parser
   * default is ['typescript', 'jsx', 'decorators-legacy', 'classProperties']
   */
  babelPlugins?: ParserPlugin[],
  /** extra babel parser options */
  babelOptions?: ParserOptions,
}

IDE / Editor config

This package uses react-dev-utils to launch your local IDE application, but, which one will be open?

In fact, it uses an environment variable named REACT_EDITOR to specify an IDE application, but if you do not set this variable, it will try to open a common IDE that you have open or installed once it is certified.

For example, if you want it always open VSCode when inspection clicked, set export REACT_EDITOR=code in your shell.


VSCode

  • install VSCode command line tools, see the official docs install-vscode-cli

  • set env to shell, like .bashrc or .zshrc

    export REACT_EDITOR=code
    

WebStorm

  • just set env with an absolute path to shell, like .bashrc or .zshrc (only MacOS)
    export REACT_EDITOR='/Applications/WebStorm.app/Contents/MacOS/webstorm'
    

OR

  • install WebStorm command line tools install-webstorm-cli

  • then set env to shell, like .bashrc or .zshrc

    export REACT_EDITOR=webstorm
    

Vim

Yes! you can also use vim if you want, just set env to shell

export REACT_EDITOR=vim

Example Project Code


How It Works

  • Stage 1 - Compile Time

    • [webpack loader] inject source file path/line/column to JSX data attributes props (use babel)
    • [webpack plugin] inject PWD (current working directory) env define for runtime
  • Stage 2 - Web React Runtime

    • [React component] Inspector Component in react, for listen hotkeys, and request api to dev-server for open IDE.

      Specific, when you click a component DOM, the Inspector will try to obtain its source file info (path/line/column) and PWD path (both injected in Stage 1), then request launch-editor api (in stage 3) with absolute file path.

  • Stage 3 - Dev-server Side

    • [middleware] setup createLaunchEditorMiddleware in webpack dev-server (or other dev-server), to open file in IDE according to the request params.

      Only need in development mode,and you want to open IDE when click a component element.

      Not need in prod mode, or you just want inspect dom without open IDE (set disableLaunchEditor={true} to Inspector component props)

Analysis of Theory


License

MIT LICENSE


Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
typescript (10,371
react (5,159
inspector (33
fiber (28
dev (20

Find Open Source By Browsing 7,000 Topics Across 59 Categories