Code Monkey home page Code Monkey logo

react-dev-inspector's Introduction

React Dev Inspector

NPM Version NPM Downloads Node.js License

Introduction

This package allows users to jump 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 hotkey (ctrl⌃ + shift⇧ + commmand⌘ + c), then click the HTML element you wish to inspect.

screen record gif (8M size):

inspector-gif

Installation

npm i -D react-dev-inspector

Usage

Users need to add React component and apply webpack config before connecting your React project with 'react-dev-inspector'.

Note: You should NOT use this package, and React component, webpack config in production mode


1. Add 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>
  )
}

2. Set up Webpack Config

There are 4 ways to set up webpack config, please pick the one fit your project best.

In common cases (like create-react-app), you can use #raw-webpack-config,

If your project happen to use webpack-chain / umi2 / umi3, you can try out our integrated plugins / helper in #usage-with-webpack-chain, #usage-with-umi2 and #usage-with-umi3.

raw webpack config

You should add:

  • an "inspector-loader"
  • a "DefinePlugin" to get current working directory
  • an api server middleware, "devServer", to open local IDE

to your current webpack config.

Example:

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())
    },
  },
}

usage with webpack-chain

This is almost equivalent to raw webpack config, except, it will NOT override devServer.before, it only adds 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
   */
}

Example Project Code


Configuration

<Inspector> Component Props

checkout TS definition under react-dev-inspector/es/Inspector.d.ts.

Property Description Type Default
keys inspector hotkeys

supported keys see: https://github.com/jaywcjlove/hotkeys#supported-keys
string[] ['control', 'shift', 'command', 'c']
disableLaunchEditor disable editor launching

(launch by default in dev Mode, but not in production mode)
boolean false
onHoverElement triggered when mouse hover in inspector mode (params: InspectParams) => void -
onClickElement triggered when mouse hover in inspector mode (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

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

react-dev-inspector's People

Contributors

zthxxx avatar thrallzhou avatar sl1673495 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.